Skip to content

[NFC][TableGen] Reorganize GlobalISelMatchTable.h/.cpp#200153

Merged
Pierre-vh merged 2 commits into
mainfrom
users/pierre-vh/rfc-reorg-tablegen-matchtable
Jun 1, 2026
Merged

[NFC][TableGen] Reorganize GlobalISelMatchTable.h/.cpp#200153
Pierre-vh merged 2 commits into
mainfrom
users/pierre-vh/rfc-reorg-tablegen-matchtable

Conversation

@Pierre-vh
Copy link
Copy Markdown
Contributor

This file was a bit of a kitchen sink, and the implementation of the
match table is sufficiently difficult to get comfortable with already.
I spent the past few weeks looking at it, finding improvements, etc. and
I think a nice way to make it a bit easier to approach is to split up
the file a bit so that the main implementation (Matchers.h/.cpp) only
contains the code pertaining to the Matchers (RuleMatchers, Preds, etc.).

We now have 3 files:

  • One for type (LLT) related utilities.
  • One for the MatchTable emission logic, which is generic and should not
    be tied to any specific implementation. It just has the tools to emit
    the opcodes for the table.
  • One for the entire Matcher system, including PredicateMatchers and so on.

This file was a bit of a kitchen sink, and the implementation of the
match table is sufficiently difficult to get comfortable with already.
I spent the past few weeks looking at it, finding improvements, etc. and
I think a nice way to make it a bit easier to approach is to split up
the file a bit so that the main implementation (Matchers.h/.cpp) only
contains the code pertaining to the Matchers (RuleMatchers, Preds, etc.).

We now have 3 files:

- One for type (LLT) related utilities.
- One for the MatchTable emission logic, which is generic and should not
  be tied to any specific implementation. It just has the tools to emit
  the opcodes for the table.
- One for the entire Matcher system, including PredicateMatchers and so on.
Copy link
Copy Markdown
Contributor Author


How to use the Graphite Merge Queue

Add the label FP Bundles to this PR to add it to the merge queue.

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

This stack of pull requests is managed by Graphite. Learn more about stacking.

Copy link
Copy Markdown
Contributor Author

This is somewhat of an RFC. I've been looking at these files for the past few weeks in search of various improvements (see previous patches, and there are some WIPs I have that im investigating too), and over these past weeks I tried a few times to split up the implementation, only to be unhappy with the result and deleting the commits, thinking it wasn't a good idea.
This time I decided to finish it and put it up for review to see what others think.

Personally I think it helps this code be a bit more maintainable by highlighting the different components of the match table system. I think we can do even more, I'd like to eventually move the entire set of classes derived from the PredicateMatcher into a standalone file, but that requires a bit more work (the Predicates aren't just simple data object, some contain pointers when they shouldn't, but it's another discussion).

My main motivation for this change is that there is growing momentum behind GlobalISel, and this is a critical part of it. It'd like to ensure this is a bit more maintainable, and that adding new stuff to these files or fixing bugs is at least a bit easier for the uninitiated.

@Pierre-vh Pierre-vh marked this pull request as ready for review May 28, 2026 10:31
@llvmorg-github-actions
Copy link
Copy Markdown

llvmorg-github-actions Bot commented May 28, 2026

@llvm/pr-subscribers-tablegen

@llvm/pr-subscribers-llvm-globalisel

Author: Pierre van Houtryve (Pierre-vh)

Changes

This file was a bit of a kitchen sink, and the implementation of the
match table is sufficiently difficult to get comfortable with already.
I spent the past few weeks looking at it, finding improvements, etc. and
I think a nice way to make it a bit easier to approach is to split up
the file a bit so that the main implementation (Matchers.h/.cpp) only
contains the code pertaining to the Matchers (RuleMatchers, Preds, etc.).

We now have 3 files:

  • One for type (LLT) related utilities.
  • One for the MatchTable emission logic, which is generic and should not
    be tied to any specific implementation. It just has the tools to emit
    the opcodes for the table.
  • One for the entire Matcher system, including PredicateMatchers and so on.

Patch is 57.01 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/200153.diff

10 Files Affected:

  • (modified) llvm/utils/TableGen/Common/CMakeLists.txt (+3-1)
  • (modified) llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.cpp (+1-1)
  • (added) llvm/utils/TableGen/Common/GlobalISel/MatchTable/MatchTable.cpp (+253)
  • (added) llvm/utils/TableGen/Common/GlobalISel/MatchTable/MatchTable.h (+180)
  • (renamed) llvm/utils/TableGen/Common/GlobalISel/MatchTable/Matchers.cpp (+20-389)
  • (renamed) llvm/utils/TableGen/Common/GlobalISel/MatchTable/Matchers.h (+12-222)
  • (added) llvm/utils/TableGen/Common/GlobalISel/MatchTable/Types.cpp (+160)
  • (added) llvm/utils/TableGen/Common/GlobalISel/MatchTable/Types.h (+86)
  • (modified) llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp (+3-3)
  • (modified) llvm/utils/TableGen/GlobalISelEmitter.cpp (+3-3)
diff --git a/llvm/utils/TableGen/Common/CMakeLists.txt b/llvm/utils/TableGen/Common/CMakeLists.txt
index 7b33c2a6e02a0..84e5e53f9fade 100644
--- a/llvm/utils/TableGen/Common/CMakeLists.txt
+++ b/llvm/utils/TableGen/Common/CMakeLists.txt
@@ -11,10 +11,12 @@ set(LLVM_LINK_COMPONENTS
   )
 
 add_llvm_library(LLVMTableGenCommon STATIC OBJECT EXCLUDE_FROM_ALL DISABLE_LLVM_LINK_LLVM_DYLIB
+  GlobalISel/MatchTable/MatchTable.cpp
+  GlobalISel/MatchTable/Matchers.cpp
+  GlobalISel/MatchTable/Types.cpp
   GlobalISel/CodeExpander.cpp
   GlobalISel/CombinerUtils.cpp
   GlobalISel/CXXPredicates.cpp
-  GlobalISel/GlobalISelMatchTable.cpp
   GlobalISel/GlobalISelMatchTableExecutorEmitter.cpp
   GlobalISel/PatternParser.cpp
   GlobalISel/Patterns.cpp
diff --git a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.cpp b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.cpp
index e9608bb7a9a7a..e59f0d8c0a7ad 100644
--- a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.cpp
+++ b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.cpp
@@ -7,7 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "GlobalISelMatchTableExecutorEmitter.h"
-#include "GlobalISelMatchTable.h"
+#include "MatchTable/Matchers.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/TableGen/CodeGenHelpers.h"
 
diff --git a/llvm/utils/TableGen/Common/GlobalISel/MatchTable/MatchTable.cpp b/llvm/utils/TableGen/Common/GlobalISel/MatchTable/MatchTable.cpp
new file mode 100644
index 0000000000000..7bebeee0db7df
--- /dev/null
+++ b/llvm/utils/TableGen/Common/GlobalISel/MatchTable/MatchTable.cpp
@@ -0,0 +1,253 @@
+//===- MatchTable.cpp -----------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "MatchTable.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/LEB128.h"
+#include "llvm/Support/ScopedPrinter.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/TableGen/Record.h"
+
+#define DEBUG_TYPE "gi-match-table"
+
+namespace llvm {
+namespace gi {
+// GIMT_Encode2/4/8
+constexpr StringLiteral EncodeMacroName = "GIMT_Encode";
+
+//===- Helpers ------------------------------------------------------------===//
+
+void emitEncodingMacrosDef(raw_ostream &OS) {
+  OS << "#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__\n"
+     << "#define " << EncodeMacroName << "2(Val)"
+     << " uint8_t(Val), uint8_t((Val) >> 8)\n"
+     << "#define " << EncodeMacroName << "4(Val)"
+     << " uint8_t(Val), uint8_t((Val) >> 8), "
+        "uint8_t((Val) >> 16), uint8_t((Val) >> 24)\n"
+     << "#define " << EncodeMacroName << "8(Val)"
+     << " uint8_t(Val), uint8_t((Val) >> 8), "
+        "uint8_t((Val) >> 16), uint8_t((Val) >> 24),  "
+        "uint8_t(uint64_t(Val) >> 32), uint8_t(uint64_t(Val) >> 40), "
+        "uint8_t(uint64_t(Val) >> 48), uint8_t(uint64_t(Val) >> 56)\n"
+     << "#else\n"
+     << "#define " << EncodeMacroName << "2(Val)"
+     << " uint8_t((Val) >> 8), uint8_t(Val)\n"
+     << "#define " << EncodeMacroName << "4(Val)"
+     << " uint8_t((Val) >> 24), uint8_t((Val) >> 16), "
+        "uint8_t((Val) >> 8), uint8_t(Val)\n"
+     << "#define " << EncodeMacroName << "8(Val)"
+     << " uint8_t(uint64_t(Val) >> 56), uint8_t(uint64_t(Val) >> 48), "
+        "uint8_t(uint64_t(Val) >> 40), uint8_t(uint64_t(Val) >> 32),  "
+        "uint8_t((Val) >> 24), uint8_t((Val) >> 16), "
+        "uint8_t((Val) >> 8), uint8_t(Val)\n"
+     << "#endif\n";
+}
+
+void emitEncodingMacrosUndef(raw_ostream &OS) {
+  OS << "#undef " << EncodeMacroName << "2\n"
+     << "#undef " << EncodeMacroName << "4\n"
+     << "#undef " << EncodeMacroName << "8\n";
+}
+
+std::string getNameForFeatureBitset(ArrayRef<const Record *> FeatureBitset,
+                                    int HwModeIdx) {
+  std::string Name = "GIFBS";
+  for (const Record *Feature : FeatureBitset)
+    Name += ("_" + Feature->getName()).str();
+  if (HwModeIdx >= 0)
+    Name += ("_HwMode" + std::to_string(HwModeIdx));
+  return Name;
+}
+
+static std::string getEncodedEmitStr(StringRef NamedValue, unsigned NumBytes) {
+  if (NumBytes == 2 || NumBytes == 4 || NumBytes == 8)
+    return (EncodeMacroName + Twine(NumBytes) + "(" + NamedValue + ")").str();
+  llvm_unreachable("Unsupported number of bytes!");
+}
+
+//===- MatchTableRecord ---------------------------------------------------===//
+
+void MatchTableRecord::emit(raw_ostream &OS, bool LineBreakIsNextAfterThis,
+                            const MatchTable &Table) const {
+  bool UseLineComment =
+      LineBreakIsNextAfterThis || (Flags & MTRF_LineBreakFollows);
+  if (Flags & (MTRF_JumpTarget | MTRF_CommaFollows))
+    UseLineComment = false;
+
+  if (Flags & MTRF_Comment)
+    OS << (UseLineComment ? "// " : "/*");
+
+  if (NumElements > 1 && !(Flags & (MTRF_PreEncoded | MTRF_Comment)))
+    OS << getEncodedEmitStr(EmitStr, NumElements);
+  else
+    OS << EmitStr;
+
+  if (Flags & MTRF_Label)
+    OS << ": @" << Table.getLabelIndex(LabelID);
+
+  if ((Flags & MTRF_Comment) && !UseLineComment)
+    OS << "*/";
+
+  if (Flags & MTRF_JumpTarget) {
+    if (Flags & MTRF_Comment)
+      OS << " ";
+    // TODO: Could encode this AOT to speed up build of generated file
+    OS << getEncodedEmitStr(llvm::to_string(Table.getLabelIndex(LabelID)),
+                            NumElements);
+  }
+
+  if (Flags & MTRF_CommaFollows) {
+    OS << ",";
+    if (!LineBreakIsNextAfterThis && !(Flags & MTRF_LineBreakFollows))
+      OS << " ";
+  }
+
+  if (Flags & MTRF_LineBreakFollows)
+    OS << "\n";
+}
+
+//===- MatchTable ---------------------------------------------------------===//
+
+MatchTableRecord MatchTable::LineBreak = {
+    std::nullopt, "" /* Emit String */, 0 /* Elements */,
+    MatchTableRecord::MTRF_LineBreakFollows};
+
+MatchTableRecord MatchTable::Comment(StringRef Comment) {
+  return MatchTableRecord(std::nullopt, Comment, 0,
+                          MatchTableRecord::MTRF_Comment);
+}
+
+MatchTableRecord MatchTable::Opcode(StringRef Opcode, int IndentAdjust) {
+  unsigned ExtraFlags = 0;
+  if (IndentAdjust > 0)
+    ExtraFlags |= MatchTableRecord::MTRF_Indent;
+  if (IndentAdjust < 0)
+    ExtraFlags |= MatchTableRecord::MTRF_Outdent;
+
+  return MatchTableRecord(std::nullopt, Opcode, 1,
+                          MatchTableRecord::MTRF_CommaFollows | ExtraFlags);
+}
+
+MatchTableRecord MatchTable::NamedValue(unsigned NumBytes,
+                                        StringRef NamedValue) {
+  return MatchTableRecord(std::nullopt, NamedValue, NumBytes,
+                          MatchTableRecord::MTRF_CommaFollows);
+}
+
+MatchTableRecord MatchTable::NamedValue(unsigned NumBytes, StringRef Namespace,
+                                        StringRef NamedValue) {
+  return MatchTableRecord(std::nullopt, (Namespace + "::" + NamedValue).str(),
+                          NumBytes, MatchTableRecord::MTRF_CommaFollows);
+}
+
+MatchTableRecord MatchTable::IntValue(unsigned NumBytes, int64_t IntValue) {
+  assert(isUIntN(NumBytes * 8, IntValue) || isIntN(NumBytes * 8, IntValue));
+  uint64_t UIntValue = IntValue;
+  if (NumBytes < 8)
+    UIntValue &= (UINT64_C(1) << NumBytes * 8) - 1;
+  std::string Str = llvm::to_string(UIntValue);
+  if (UIntValue > INT64_MAX)
+    Str += 'u';
+  // TODO: Could optimize this directly to save the compiler some work when
+  // building the file
+  return MatchTableRecord(std::nullopt, Str, NumBytes,
+                          MatchTableRecord::MTRF_CommaFollows);
+}
+
+MatchTableRecord MatchTable::ULEB128Value(uint64_t IntValue) {
+  uint8_t Buffer[10];
+  unsigned Len = encodeULEB128(IntValue, Buffer);
+
+  // Simple case (most common)
+  if (Len == 1) {
+    return MatchTableRecord(std::nullopt, llvm::to_string((unsigned)Buffer[0]),
+                            1, MatchTableRecord::MTRF_CommaFollows);
+  }
+
+  // Print it as, e.g. /* -123456 (*/, 0xC0, 0xBB, 0x78 /*)*/
+  std::string Str;
+  raw_string_ostream OS(Str);
+  OS << "/* " << llvm::to_string(IntValue) << "(*/";
+  for (unsigned K = 0; K < Len; ++K) {
+    if (K)
+      OS << ", ";
+    OS << "0x" << llvm::toHex({Buffer[K]});
+  }
+  OS << "/*)*/";
+  return MatchTableRecord(std::nullopt, Str, Len,
+                          MatchTableRecord::MTRF_CommaFollows |
+                              MatchTableRecord::MTRF_PreEncoded);
+}
+
+MatchTableRecord MatchTable::Label(unsigned LabelID) {
+  return MatchTableRecord(LabelID, "Label " + llvm::to_string(LabelID), 0,
+                          MatchTableRecord::MTRF_Label |
+                              MatchTableRecord::MTRF_Comment |
+                              MatchTableRecord::MTRF_LineBreakFollows);
+}
+
+MatchTableRecord MatchTable::JumpTarget(unsigned LabelID) {
+  return MatchTableRecord(LabelID, "Label " + llvm::to_string(LabelID), 4,
+                          MatchTableRecord::MTRF_JumpTarget |
+                              MatchTableRecord::MTRF_Comment |
+                              MatchTableRecord::MTRF_CommaFollows);
+}
+
+void MatchTable::emitUse(raw_ostream &OS) const { OS << "MatchTable" << ID; }
+
+void MatchTable::emitDeclaration(raw_ostream &OS) const {
+  static constexpr unsigned BaseIndent = 4;
+  unsigned Indentation = 0;
+  OS << "  constexpr static uint8_t MatchTable" << ID << "[] = {";
+  LineBreak.emit(OS, true, *this);
+
+  // We want to display the table index of each line in a consistent
+  // manner. It has to appear as a column on the left side of the table.
+  // To determine how wide the column needs to be, check how many characters
+  // we need to fit the largest possible index in the current table.
+  const unsigned NumColsForIdx = llvm::to_string(CurrentSize).size();
+
+  unsigned CurIndex = 0;
+  const auto BeginLine = [&]() {
+    OS.indent(BaseIndent);
+    std::string IdxStr = llvm::to_string(CurIndex);
+    // Pad the string with spaces to keep the size of the prefix consistent.
+    OS << " /* ";
+    OS.indent(NumColsForIdx - IdxStr.size()) << IdxStr << " */ ";
+    OS.indent(Indentation);
+  };
+
+  BeginLine();
+  for (auto I = Contents.begin(), E = Contents.end(); I != E; ++I) {
+    bool LineBreakIsNext = false;
+    const auto &NextI = std::next(I);
+
+    if (NextI != E) {
+      if (NextI->EmitStr == "" &&
+          NextI->Flags == MatchTableRecord::MTRF_LineBreakFollows)
+        LineBreakIsNext = true;
+    }
+
+    if (I->Flags & MatchTableRecord::MTRF_Indent)
+      Indentation += 2;
+
+    I->emit(OS, LineBreakIsNext, *this);
+    if (I->Flags & MatchTableRecord::MTRF_LineBreakFollows)
+      BeginLine();
+
+    if (I->Flags & MatchTableRecord::MTRF_Outdent)
+      Indentation -= 2;
+
+    CurIndex += I->size();
+  }
+  assert(CurIndex == CurrentSize);
+  OS << "}; // Size: " << CurrentSize << " bytes\n";
+}
+
+} // namespace gi
+} // namespace llvm
diff --git a/llvm/utils/TableGen/Common/GlobalISel/MatchTable/MatchTable.h b/llvm/utils/TableGen/Common/GlobalISel/MatchTable/MatchTable.h
new file mode 100644
index 0000000000000..59c6173fd0445
--- /dev/null
+++ b/llvm/utils/TableGen/Common/GlobalISel/MatchTable/MatchTable.h
@@ -0,0 +1,180 @@
+//===- MatchTable.h -------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file
+/// This file contains the generic emitter for the GlobalISel Match Table
+/// system. This file only contains the code used to emit the table itself.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_UTILS_TABLEGEN_COMMON_GLOBALISEL_MATCHTABLE_MATCHTABLE_H
+#define LLVM_UTILS_TABLEGEN_COMMON_GLOBALISEL_MATCHTABLE_MATCHTABLE_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringRef.h"
+#include <string>
+
+namespace llvm {
+class raw_ostream;
+class Record;
+namespace gi {
+class Matcher;
+class MatchTable;
+
+//===- Helper functions ---------------------------------------------------===//
+
+void emitEncodingMacrosDef(raw_ostream &OS);
+void emitEncodingMacrosUndef(raw_ostream &OS);
+
+std::string getNameForFeatureBitset(ArrayRef<const Record *> FeatureBitset,
+                                    int HwModeIdx);
+
+/// A record to be stored in a MatchTable.
+///
+/// This class represents any and all output that may be required to emit the
+/// MatchTable. Instances  are most often configured to represent an opcode or
+/// value that will be emitted to the table with some formatting but it can also
+/// represent commas, comments, and other formatting instructions.
+struct MatchTableRecord {
+  enum RecordFlagsBits {
+    MTRF_None = 0x0,
+    /// Causes EmitStr to be formatted as comment when emitted.
+    MTRF_Comment = 0x1,
+    /// Causes the record value to be followed by a comma when emitted.
+    MTRF_CommaFollows = 0x2,
+    /// Causes the record value to be followed by a line break when emitted.
+    MTRF_LineBreakFollows = 0x4,
+    /// Indicates that the record defines a label and causes an additional
+    /// comment to be emitted containing the index of the label.
+    MTRF_Label = 0x8,
+    /// Causes the record to be emitted as the index of the label specified by
+    /// LabelID along with a comment indicating where that label is.
+    MTRF_JumpTarget = 0x10,
+    /// Causes the formatter to add a level of indentation before emitting the
+    /// record.
+    MTRF_Indent = 0x20,
+    /// Causes the formatter to remove a level of indentation after emitting the
+    /// record.
+    MTRF_Outdent = 0x40,
+    /// Causes the formatter to not use encoding macros to emit this multi-byte
+    /// value.
+    MTRF_PreEncoded = 0x80,
+  };
+
+  /// When MTRF_Label or MTRF_JumpTarget is used, indicates a label id to
+  /// reference or define.
+  unsigned LabelID;
+  /// The string to emit. Depending on the MTRF_* flags it may be a comment, a
+  /// value, a label name.
+  std::string EmitStr;
+
+private:
+  /// The number of MatchTable elements described by this record. Comments are 0
+  /// while values are typically 1. Values >1 may occur when we need to emit
+  /// values that exceed the size of a MatchTable element.
+  unsigned NumElements;
+
+public:
+  /// A bitfield of RecordFlagsBits flags.
+  unsigned Flags;
+
+  MatchTableRecord(std::optional<unsigned> LabelID_, StringRef EmitStr,
+                   unsigned NumElements, unsigned Flags)
+      : LabelID(LabelID_.value_or(~0u)), EmitStr(EmitStr),
+        NumElements(NumElements), Flags(Flags) {
+    assert((!LabelID_ || LabelID != ~0u) &&
+           "This value is reserved for non-labels");
+  }
+  MatchTableRecord(const MatchTableRecord &Other) = default;
+  MatchTableRecord(MatchTableRecord &&Other) = default;
+
+  /// Useful if a Match Table Record gets optimized out
+  void turnIntoComment() {
+    Flags |= MTRF_Comment;
+    Flags &= ~MTRF_CommaFollows;
+    NumElements = 0;
+  }
+
+  void emit(raw_ostream &OS, bool LineBreakNextAfterThis,
+            const MatchTable &Table) const;
+  unsigned size() const { return NumElements; }
+};
+
+/// Holds the contents of a generated MatchTable to enable formatting and the
+/// necessary index tracking needed to support GIM_Try.
+class MatchTable {
+  /// An unique identifier for the table. The generated table will be named
+  /// MatchTable${ID}.
+  unsigned ID;
+  /// The records that make up the table. Also includes comments describing the
+  /// values being emitted and line breaks to format it.
+  std::vector<MatchTableRecord> Contents;
+  /// The currently defined labels.
+  DenseMap<unsigned, unsigned> LabelMap;
+  /// Tracks the sum of MatchTableRecord::NumElements as the table is built.
+  unsigned CurrentSize = 0;
+  /// A unique identifier for a MatchTable label.
+  unsigned CurrentLabelID = 0;
+  /// Determines if the table should be instrumented for rule coverage tracking.
+  bool IsWithCoverage;
+  /// Whether this table is for the GISel combiner.
+  bool IsCombinerTable;
+
+public:
+  static MatchTableRecord LineBreak;
+  static MatchTableRecord Comment(StringRef Comment);
+  static MatchTableRecord Opcode(StringRef Opcode, int IndentAdjust = 0);
+  static MatchTableRecord NamedValue(unsigned NumBytes, StringRef NamedValue);
+  static MatchTableRecord NamedValue(unsigned NumBytes, StringRef Namespace,
+                                     StringRef NamedValue);
+  static MatchTableRecord IntValue(unsigned NumBytes, int64_t IntValue);
+  static MatchTableRecord ULEB128Value(uint64_t IntValue);
+  static MatchTableRecord Label(unsigned LabelID);
+  static MatchTableRecord JumpTarget(unsigned LabelID);
+
+  MatchTable(bool WithCoverage, bool IsCombinerTable, unsigned ID = 0)
+      : ID(ID), IsWithCoverage(WithCoverage), IsCombinerTable(IsCombinerTable) {
+  }
+
+  bool isWithCoverage() const { return IsWithCoverage; }
+  bool isCombiner() const { return IsCombinerTable; }
+
+  void push_back(const MatchTableRecord &Value) {
+    if (Value.Flags & MatchTableRecord::MTRF_Label)
+      defineLabel(Value.LabelID);
+    Contents.push_back(Value);
+    CurrentSize += Value.size();
+  }
+
+  unsigned allocateLabelID() { return CurrentLabelID++; }
+
+  void defineLabel(unsigned LabelID) {
+    LabelMap.try_emplace(LabelID, CurrentSize);
+  }
+
+  unsigned getLabelIndex(unsigned LabelID) const {
+    const auto I = LabelMap.find(LabelID);
+    assert(I != LabelMap.end() && "Use of undeclared label");
+    return I->second;
+  }
+
+  void emitUse(raw_ostream &OS) const;
+  void emitDeclaration(raw_ostream &OS) const;
+};
+
+inline MatchTable &operator<<(MatchTable &Table,
+                              const MatchTableRecord &Value) {
+  Table.push_back(Value);
+  return Table;
+}
+
+} // namespace gi
+} // namespace llvm
+
+#endif
diff --git a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp b/llvm/utils/TableGen/Common/GlobalISel/MatchTable/Matchers.cpp
similarity index 86%
rename from llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp
rename to llvm/utils/TableGen/Common/GlobalISel/MatchTable/Matchers.cpp
index 9b7584c00ddd3..92fa3c224a497 100644
--- a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp
+++ b/llvm/utils/TableGen/Common/GlobalISel/MatchTable/Matchers.cpp
@@ -1,4 +1,4 @@
-//===- GlobalISelMatchTable.cpp -------------------------------------------===//
+//===- Matchers.cpp -------------------------------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -6,7 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "GlobalISelMatchTable.h"
+#include "Matchers.h"
 #include "Common/CodeGenInstruction.h"
 #include "Common/CodeGenRegisters.h"
 #include "llvm/ADT/Statistic.h"
@@ -17,7 +17,7 @@
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/TableGen/Error.h"
 
-#define DEBUG_TYPE "gi-match-table"
+#define DEBUG_TYPE "gi-match-table-matchers"
 
 STATISTIC(NumPatternEmitted, "Number of patterns emitted");
 
@@ -44,54 +44,8 @@ getMatchOpcodeForImmPredicate(const TreePredicateFn &Predicate) {
   return "GIM_Check" + Predicate.getImmTypeIdentifier().str() + "ImmPredicate";
 }
 
-// GIMT_Encode2/4/8
-constexpr StringLiteral EncodeMacroName = "GIMT_Encode";
-
 //===- Helpers ------------------------------------------------------------===//
 
-void llvm::gi::emitEncodingMacrosDef(raw_ostream &OS) {
-  OS << "#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__\n"
-     << "#define " << EncodeMacroName << "2(Val)"
-     << " uint8_t(Val), uint8_t((Val) >> 8)\n"
-     << "#define " << EncodeMacroName << "4(Val)"
-     << " uint8_t(Val), uint8_t((Val) >> 8), "
-        "uint8_t((Val) >> 16), uint8_t((Val) >> 24)\n"
-     << "#define " << EncodeMacroName << "8(Val)"
-     << " uint8_t(Val), uint8_t((Val) >> 8), "
-        "uint8...
[truncated]

@Pierre-vh Pierre-vh changed the title [NFC][TableGen] Reorganize GlobalISelMatchTable.h [NFC][TableGen] Reorganize GlobalISelMatchTable.h/.cpp May 29, 2026
@Pierre-vh Pierre-vh merged commit 7a435ca into main Jun 1, 2026
10 checks passed
@Pierre-vh Pierre-vh deleted the users/pierre-vh/rfc-reorg-tablegen-matchtable branch June 1, 2026 07:40
@llvm-ci
Copy link
Copy Markdown

llvm-ci commented Jun 1, 2026

LLVM Buildbot has detected a new failure on builder openmp-s390x-linux running on systemz-1 while building llvm at step 6 "test-openmp".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/88/builds/23394

Here is the relevant piece of the build log for the reference
Step 6 (test-openmp) failure: test (failure)
******************** TEST 'libomp :: tasking/issue-94260-2.c' FAILED ********************
Exit Code: -11

Command Output (stdout):
--
# RUN: at line 1
/home/uweigand/sandbox/buildbot/openmp-s390x-linux/llvm.build/./bin/clang -fopenmp   -I /home/uweigand/sandbox/buildbot/openmp-s390x-linux/llvm.build/runtimes/runtimes-bins/openmp/runtime/src -I /home/uweigand/sandbox/buildbot/openmp-s390x-linux/llvm.src/openmp/runtime/test -L /home/uweigand/sandbox/buildbot/openmp-s390x-linux/llvm.build/runtimes/runtimes-bins/openmp/runtime/src  -fno-omit-frame-pointer -mbackchain -I /home/uweigand/sandbox/buildbot/openmp-s390x-linux/llvm.src/openmp/runtime/test/ompt /home/uweigand/sandbox/buildbot/openmp-s390x-linux/llvm.src/openmp/runtime/test/tasking/issue-94260-2.c -o /home/uweigand/sandbox/buildbot/openmp-s390x-linux/llvm.build/runtimes/runtimes-bins/openmp/runtime/test/tasking/Output/issue-94260-2.c.tmp -lm -latomic && /home/uweigand/sandbox/buildbot/openmp-s390x-linux/llvm.build/runtimes/runtimes-bins/openmp/runtime/test/tasking/Output/issue-94260-2.c.tmp
# executed command: /home/uweigand/sandbox/buildbot/openmp-s390x-linux/llvm.build/./bin/clang -fopenmp -I /home/uweigand/sandbox/buildbot/openmp-s390x-linux/llvm.build/runtimes/runtimes-bins/openmp/runtime/src -I /home/uweigand/sandbox/buildbot/openmp-s390x-linux/llvm.src/openmp/runtime/test -L /home/uweigand/sandbox/buildbot/openmp-s390x-linux/llvm.build/runtimes/runtimes-bins/openmp/runtime/src -fno-omit-frame-pointer -mbackchain -I /home/uweigand/sandbox/buildbot/openmp-s390x-linux/llvm.src/openmp/runtime/test/ompt /home/uweigand/sandbox/buildbot/openmp-s390x-linux/llvm.src/openmp/runtime/test/tasking/issue-94260-2.c -o /home/uweigand/sandbox/buildbot/openmp-s390x-linux/llvm.build/runtimes/runtimes-bins/openmp/runtime/test/tasking/Output/issue-94260-2.c.tmp -lm -latomic
# executed command: /home/uweigand/sandbox/buildbot/openmp-s390x-linux/llvm.build/runtimes/runtimes-bins/openmp/runtime/test/tasking/Output/issue-94260-2.c.tmp
# note: command had no output on stdout or stderr
# error: command failed with exit status: -11

--

********************


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants