Skip to content

Commit 7a435ca

Browse files
authored
[NFC][TableGen] Reorganize GlobalISelMatchTable.h/.cpp (#200153)
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.
1 parent 6a33d3f commit 7a435ca

10 files changed

Lines changed: 719 additions & 619 deletions

File tree

llvm/utils/TableGen/Common/CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,12 @@ set(LLVM_LINK_COMPONENTS
1111
)
1212

1313
add_llvm_library(LLVMTableGenCommon STATIC OBJECT EXCLUDE_FROM_ALL DISABLE_LLVM_LINK_LLVM_DYLIB
14+
GlobalISel/MatchTable/MatchTable.cpp
15+
GlobalISel/MatchTable/Matchers.cpp
16+
GlobalISel/MatchTable/Types.cpp
1417
GlobalISel/CodeExpander.cpp
1518
GlobalISel/CombinerUtils.cpp
1619
GlobalISel/CXXPredicates.cpp
17-
GlobalISel/GlobalISelMatchTable.cpp
1820
GlobalISel/GlobalISelMatchTableExecutorEmitter.cpp
1921
GlobalISel/PatternParser.cpp
2022
GlobalISel/Patterns.cpp

llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "GlobalISelMatchTableExecutorEmitter.h"
10-
#include "GlobalISelMatchTable.h"
10+
#include "MatchTable/Matchers.h"
1111
#include "llvm/Support/CommandLine.h"
1212
#include "llvm/TableGen/CodeGenHelpers.h"
1313

Lines changed: 253 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,253 @@
1+
//===- MatchTable.cpp -----------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "MatchTable.h"
10+
#include "llvm/ADT/Twine.h"
11+
#include "llvm/Support/LEB128.h"
12+
#include "llvm/Support/ScopedPrinter.h"
13+
#include "llvm/Support/raw_ostream.h"
14+
#include "llvm/TableGen/Record.h"
15+
16+
#define DEBUG_TYPE "gi-match-table"
17+
18+
namespace llvm {
19+
namespace gi {
20+
// GIMT_Encode2/4/8
21+
constexpr StringLiteral EncodeMacroName = "GIMT_Encode";
22+
23+
//===- Helpers ------------------------------------------------------------===//
24+
25+
void emitEncodingMacrosDef(raw_ostream &OS) {
26+
OS << "#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__\n"
27+
<< "#define " << EncodeMacroName << "2(Val)"
28+
<< " uint8_t(Val), uint8_t((Val) >> 8)\n"
29+
<< "#define " << EncodeMacroName << "4(Val)"
30+
<< " uint8_t(Val), uint8_t((Val) >> 8), "
31+
"uint8_t((Val) >> 16), uint8_t((Val) >> 24)\n"
32+
<< "#define " << EncodeMacroName << "8(Val)"
33+
<< " uint8_t(Val), uint8_t((Val) >> 8), "
34+
"uint8_t((Val) >> 16), uint8_t((Val) >> 24), "
35+
"uint8_t(uint64_t(Val) >> 32), uint8_t(uint64_t(Val) >> 40), "
36+
"uint8_t(uint64_t(Val) >> 48), uint8_t(uint64_t(Val) >> 56)\n"
37+
<< "#else\n"
38+
<< "#define " << EncodeMacroName << "2(Val)"
39+
<< " uint8_t((Val) >> 8), uint8_t(Val)\n"
40+
<< "#define " << EncodeMacroName << "4(Val)"
41+
<< " uint8_t((Val) >> 24), uint8_t((Val) >> 16), "
42+
"uint8_t((Val) >> 8), uint8_t(Val)\n"
43+
<< "#define " << EncodeMacroName << "8(Val)"
44+
<< " uint8_t(uint64_t(Val) >> 56), uint8_t(uint64_t(Val) >> 48), "
45+
"uint8_t(uint64_t(Val) >> 40), uint8_t(uint64_t(Val) >> 32), "
46+
"uint8_t((Val) >> 24), uint8_t((Val) >> 16), "
47+
"uint8_t((Val) >> 8), uint8_t(Val)\n"
48+
<< "#endif\n";
49+
}
50+
51+
void emitEncodingMacrosUndef(raw_ostream &OS) {
52+
OS << "#undef " << EncodeMacroName << "2\n"
53+
<< "#undef " << EncodeMacroName << "4\n"
54+
<< "#undef " << EncodeMacroName << "8\n";
55+
}
56+
57+
std::string getNameForFeatureBitset(ArrayRef<const Record *> FeatureBitset,
58+
int HwModeIdx) {
59+
std::string Name = "GIFBS";
60+
for (const Record *Feature : FeatureBitset)
61+
Name += ("_" + Feature->getName()).str();
62+
if (HwModeIdx >= 0)
63+
Name += ("_HwMode" + std::to_string(HwModeIdx));
64+
return Name;
65+
}
66+
67+
static std::string getEncodedEmitStr(StringRef NamedValue, unsigned NumBytes) {
68+
if (NumBytes == 2 || NumBytes == 4 || NumBytes == 8)
69+
return (EncodeMacroName + Twine(NumBytes) + "(" + NamedValue + ")").str();
70+
llvm_unreachable("Unsupported number of bytes!");
71+
}
72+
73+
//===- MatchTableRecord ---------------------------------------------------===//
74+
75+
void MatchTableRecord::emit(raw_ostream &OS, bool LineBreakIsNextAfterThis,
76+
const MatchTable &Table) const {
77+
bool UseLineComment =
78+
LineBreakIsNextAfterThis || (Flags & MTRF_LineBreakFollows);
79+
if (Flags & (MTRF_JumpTarget | MTRF_CommaFollows))
80+
UseLineComment = false;
81+
82+
if (Flags & MTRF_Comment)
83+
OS << (UseLineComment ? "// " : "/*");
84+
85+
if (NumElements > 1 && !(Flags & (MTRF_PreEncoded | MTRF_Comment)))
86+
OS << getEncodedEmitStr(EmitStr, NumElements);
87+
else
88+
OS << EmitStr;
89+
90+
if (Flags & MTRF_Label)
91+
OS << ": @" << Table.getLabelIndex(LabelID);
92+
93+
if ((Flags & MTRF_Comment) && !UseLineComment)
94+
OS << "*/";
95+
96+
if (Flags & MTRF_JumpTarget) {
97+
if (Flags & MTRF_Comment)
98+
OS << " ";
99+
// TODO: Could encode this AOT to speed up build of generated file
100+
OS << getEncodedEmitStr(llvm::to_string(Table.getLabelIndex(LabelID)),
101+
NumElements);
102+
}
103+
104+
if (Flags & MTRF_CommaFollows) {
105+
OS << ",";
106+
if (!LineBreakIsNextAfterThis && !(Flags & MTRF_LineBreakFollows))
107+
OS << " ";
108+
}
109+
110+
if (Flags & MTRF_LineBreakFollows)
111+
OS << "\n";
112+
}
113+
114+
//===- MatchTable ---------------------------------------------------------===//
115+
116+
MatchTableRecord MatchTable::LineBreak = {
117+
std::nullopt, "" /* Emit String */, 0 /* Elements */,
118+
MatchTableRecord::MTRF_LineBreakFollows};
119+
120+
MatchTableRecord MatchTable::Comment(StringRef Comment) {
121+
return MatchTableRecord(std::nullopt, Comment, 0,
122+
MatchTableRecord::MTRF_Comment);
123+
}
124+
125+
MatchTableRecord MatchTable::Opcode(StringRef Opcode, int IndentAdjust) {
126+
unsigned ExtraFlags = 0;
127+
if (IndentAdjust > 0)
128+
ExtraFlags |= MatchTableRecord::MTRF_Indent;
129+
if (IndentAdjust < 0)
130+
ExtraFlags |= MatchTableRecord::MTRF_Outdent;
131+
132+
return MatchTableRecord(std::nullopt, Opcode, 1,
133+
MatchTableRecord::MTRF_CommaFollows | ExtraFlags);
134+
}
135+
136+
MatchTableRecord MatchTable::NamedValue(unsigned NumBytes,
137+
StringRef NamedValue) {
138+
return MatchTableRecord(std::nullopt, NamedValue, NumBytes,
139+
MatchTableRecord::MTRF_CommaFollows);
140+
}
141+
142+
MatchTableRecord MatchTable::NamedValue(unsigned NumBytes, StringRef Namespace,
143+
StringRef NamedValue) {
144+
return MatchTableRecord(std::nullopt, (Namespace + "::" + NamedValue).str(),
145+
NumBytes, MatchTableRecord::MTRF_CommaFollows);
146+
}
147+
148+
MatchTableRecord MatchTable::IntValue(unsigned NumBytes, int64_t IntValue) {
149+
assert(isUIntN(NumBytes * 8, IntValue) || isIntN(NumBytes * 8, IntValue));
150+
uint64_t UIntValue = IntValue;
151+
if (NumBytes < 8)
152+
UIntValue &= (UINT64_C(1) << NumBytes * 8) - 1;
153+
std::string Str = llvm::to_string(UIntValue);
154+
if (UIntValue > INT64_MAX)
155+
Str += 'u';
156+
// TODO: Could optimize this directly to save the compiler some work when
157+
// building the file
158+
return MatchTableRecord(std::nullopt, Str, NumBytes,
159+
MatchTableRecord::MTRF_CommaFollows);
160+
}
161+
162+
MatchTableRecord MatchTable::ULEB128Value(uint64_t IntValue) {
163+
uint8_t Buffer[10];
164+
unsigned Len = encodeULEB128(IntValue, Buffer);
165+
166+
// Simple case (most common)
167+
if (Len == 1) {
168+
return MatchTableRecord(std::nullopt, llvm::to_string((unsigned)Buffer[0]),
169+
1, MatchTableRecord::MTRF_CommaFollows);
170+
}
171+
172+
// Print it as, e.g. /* -123456 (*/, 0xC0, 0xBB, 0x78 /*)*/
173+
std::string Str;
174+
raw_string_ostream OS(Str);
175+
OS << "/* " << llvm::to_string(IntValue) << "(*/";
176+
for (unsigned K = 0; K < Len; ++K) {
177+
if (K)
178+
OS << ", ";
179+
OS << "0x" << llvm::toHex({Buffer[K]});
180+
}
181+
OS << "/*)*/";
182+
return MatchTableRecord(std::nullopt, Str, Len,
183+
MatchTableRecord::MTRF_CommaFollows |
184+
MatchTableRecord::MTRF_PreEncoded);
185+
}
186+
187+
MatchTableRecord MatchTable::Label(unsigned LabelID) {
188+
return MatchTableRecord(LabelID, "Label " + llvm::to_string(LabelID), 0,
189+
MatchTableRecord::MTRF_Label |
190+
MatchTableRecord::MTRF_Comment |
191+
MatchTableRecord::MTRF_LineBreakFollows);
192+
}
193+
194+
MatchTableRecord MatchTable::JumpTarget(unsigned LabelID) {
195+
return MatchTableRecord(LabelID, "Label " + llvm::to_string(LabelID), 4,
196+
MatchTableRecord::MTRF_JumpTarget |
197+
MatchTableRecord::MTRF_Comment |
198+
MatchTableRecord::MTRF_CommaFollows);
199+
}
200+
201+
void MatchTable::emitUse(raw_ostream &OS) const { OS << "MatchTable" << ID; }
202+
203+
void MatchTable::emitDeclaration(raw_ostream &OS) const {
204+
static constexpr unsigned BaseIndent = 4;
205+
unsigned Indentation = 0;
206+
OS << " constexpr static uint8_t MatchTable" << ID << "[] = {";
207+
LineBreak.emit(OS, true, *this);
208+
209+
// We want to display the table index of each line in a consistent
210+
// manner. It has to appear as a column on the left side of the table.
211+
// To determine how wide the column needs to be, check how many characters
212+
// we need to fit the largest possible index in the current table.
213+
const unsigned NumColsForIdx = llvm::to_string(CurrentSize).size();
214+
215+
unsigned CurIndex = 0;
216+
const auto BeginLine = [&]() {
217+
OS.indent(BaseIndent);
218+
std::string IdxStr = llvm::to_string(CurIndex);
219+
// Pad the string with spaces to keep the size of the prefix consistent.
220+
OS << " /* ";
221+
OS.indent(NumColsForIdx - IdxStr.size()) << IdxStr << " */ ";
222+
OS.indent(Indentation);
223+
};
224+
225+
BeginLine();
226+
for (auto I = Contents.begin(), E = Contents.end(); I != E; ++I) {
227+
bool LineBreakIsNext = false;
228+
const auto &NextI = std::next(I);
229+
230+
if (NextI != E) {
231+
if (NextI->EmitStr == "" &&
232+
NextI->Flags == MatchTableRecord::MTRF_LineBreakFollows)
233+
LineBreakIsNext = true;
234+
}
235+
236+
if (I->Flags & MatchTableRecord::MTRF_Indent)
237+
Indentation += 2;
238+
239+
I->emit(OS, LineBreakIsNext, *this);
240+
if (I->Flags & MatchTableRecord::MTRF_LineBreakFollows)
241+
BeginLine();
242+
243+
if (I->Flags & MatchTableRecord::MTRF_Outdent)
244+
Indentation -= 2;
245+
246+
CurIndex += I->size();
247+
}
248+
assert(CurIndex == CurrentSize);
249+
OS << "}; // Size: " << CurrentSize << " bytes\n";
250+
}
251+
252+
} // namespace gi
253+
} // namespace llvm

0 commit comments

Comments
 (0)