Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp
35258 views
1
//===- GlobalISelCombinerMatchTableEmitter.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
/// \file Generate a combiner implementation for GlobalISel from a declarative
10
/// syntax using GlobalISelMatchTable.
11
///
12
/// Usually, TableGen backends use "assert is an error" as a means to report
13
/// invalid input. They try to diagnose common case but don't try very hard and
14
/// crashes can be common. This backend aims to behave closer to how a language
15
/// compiler frontend would behave: we try extra hard to diagnose invalid inputs
16
/// early, and any crash should be considered a bug (= a feature or diagnostic
17
/// is missing).
18
///
19
/// While this can make the backend a bit more complex than it needs to be, it
20
/// pays off because MIR patterns can get complicated. Giving useful error
21
/// messages to combine writers can help boost their productivity.
22
///
23
/// As with anything, a good balance has to be found. We also don't want to
24
/// write hundreds of lines of code to detect edge cases. In practice, crashing
25
/// very occasionally, or giving poor errors in some rare instances, is fine.
26
///
27
//===----------------------------------------------------------------------===//
28
29
#include "Basic/CodeGenIntrinsics.h"
30
#include "Common/CodeGenInstruction.h"
31
#include "Common/CodeGenTarget.h"
32
#include "Common/GlobalISel/CXXPredicates.h"
33
#include "Common/GlobalISel/CodeExpander.h"
34
#include "Common/GlobalISel/CodeExpansions.h"
35
#include "Common/GlobalISel/CombinerUtils.h"
36
#include "Common/GlobalISel/GlobalISelMatchTable.h"
37
#include "Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.h"
38
#include "Common/GlobalISel/PatternParser.h"
39
#include "Common/GlobalISel/Patterns.h"
40
#include "Common/SubtargetFeatureInfo.h"
41
#include "llvm/ADT/APInt.h"
42
#include "llvm/ADT/EquivalenceClasses.h"
43
#include "llvm/ADT/Hashing.h"
44
#include "llvm/ADT/MapVector.h"
45
#include "llvm/ADT/SetVector.h"
46
#include "llvm/ADT/Statistic.h"
47
#include "llvm/ADT/StringExtras.h"
48
#include "llvm/ADT/StringSet.h"
49
#include "llvm/Support/CommandLine.h"
50
#include "llvm/Support/Debug.h"
51
#include "llvm/Support/PrettyStackTrace.h"
52
#include "llvm/Support/ScopedPrinter.h"
53
#include "llvm/TableGen/Error.h"
54
#include "llvm/TableGen/Record.h"
55
#include "llvm/TableGen/StringMatcher.h"
56
#include "llvm/TableGen/TableGenBackend.h"
57
#include <cstdint>
58
59
using namespace llvm;
60
using namespace llvm::gi;
61
62
#define DEBUG_TYPE "gicombiner-emitter"
63
64
namespace {
65
cl::OptionCategory
66
GICombinerEmitterCat("Options for -gen-global-isel-combiner");
67
cl::opt<bool> StopAfterParse(
68
"gicombiner-stop-after-parse",
69
cl::desc("Stop processing after parsing rules and dump state"),
70
cl::cat(GICombinerEmitterCat));
71
cl::list<std::string>
72
SelectedCombiners("combiners", cl::desc("Emit the specified combiners"),
73
cl::cat(GICombinerEmitterCat), cl::CommaSeparated);
74
cl::opt<bool> DebugCXXPreds(
75
"gicombiner-debug-cxxpreds",
76
cl::desc("Add Contextual/Debug comments to all C++ predicates"),
77
cl::cat(GICombinerEmitterCat));
78
cl::opt<bool> DebugTypeInfer("gicombiner-debug-typeinfer",
79
cl::desc("Print type inference debug logs"),
80
cl::cat(GICombinerEmitterCat));
81
82
constexpr StringLiteral CXXCustomActionPrefix = "GICXXCustomAction_";
83
constexpr StringLiteral CXXPredPrefix = "GICXXPred_MI_Predicate_";
84
constexpr StringLiteral MatchDataClassName = "GIDefMatchData";
85
86
//===- CodeExpansions Helpers --------------------------------------------===//
87
88
void declareInstExpansion(CodeExpansions &CE, const InstructionMatcher &IM,
89
StringRef Name) {
90
CE.declare(Name, "State.MIs[" + to_string(IM.getInsnVarID()) + "]");
91
}
92
93
void declareInstExpansion(CodeExpansions &CE, const BuildMIAction &A,
94
StringRef Name) {
95
// Note: we use redeclare here because this may overwrite a matcher inst
96
// expansion.
97
CE.redeclare(Name, "OutMIs[" + to_string(A.getInsnID()) + "]");
98
}
99
100
void declareOperandExpansion(CodeExpansions &CE, const OperandMatcher &OM,
101
StringRef Name) {
102
CE.declare(Name, "State.MIs[" + to_string(OM.getInsnVarID()) +
103
"]->getOperand(" + to_string(OM.getOpIdx()) + ")");
104
}
105
106
void declareTempRegExpansion(CodeExpansions &CE, unsigned TempRegID,
107
StringRef Name) {
108
CE.declare(Name, "State.TempRegisters[" + to_string(TempRegID) + "]");
109
}
110
111
//===- Misc. Helpers -----------------------------------------------------===//
112
113
template <typename Container> auto keys(Container &&C) {
114
return map_range(C, [](auto &Entry) -> auto & { return Entry.first; });
115
}
116
117
template <typename Container> auto values(Container &&C) {
118
return map_range(C, [](auto &Entry) -> auto & { return Entry.second; });
119
}
120
121
std::string getIsEnabledPredicateEnumName(unsigned CombinerRuleID) {
122
return "GICXXPred_Simple_IsRule" + to_string(CombinerRuleID) + "Enabled";
123
}
124
125
//===- MatchTable Helpers ------------------------------------------------===//
126
127
LLTCodeGen getLLTCodeGen(const PatternType &PT) {
128
return *MVTToLLT(getValueType(PT.getLLTRecord()));
129
}
130
131
LLTCodeGenOrTempType getLLTCodeGenOrTempType(const PatternType &PT,
132
RuleMatcher &RM) {
133
assert(!PT.isNone());
134
135
if (PT.isLLT())
136
return getLLTCodeGen(PT);
137
138
assert(PT.isTypeOf());
139
auto &OM = RM.getOperandMatcher(PT.getTypeOfOpName());
140
return OM.getTempTypeIdx(RM);
141
}
142
143
//===- PrettyStackTrace Helpers ------------------------------------------===//
144
145
class PrettyStackTraceParse : public PrettyStackTraceEntry {
146
const Record &Def;
147
148
public:
149
PrettyStackTraceParse(const Record &Def) : Def(Def) {}
150
151
void print(raw_ostream &OS) const override {
152
if (Def.isSubClassOf("GICombineRule"))
153
OS << "Parsing GICombineRule '" << Def.getName() << "'";
154
else if (Def.isSubClassOf(PatFrag::ClassName))
155
OS << "Parsing " << PatFrag::ClassName << " '" << Def.getName() << "'";
156
else
157
OS << "Parsing '" << Def.getName() << "'";
158
OS << '\n';
159
}
160
};
161
162
class PrettyStackTraceEmit : public PrettyStackTraceEntry {
163
const Record &Def;
164
const Pattern *Pat = nullptr;
165
166
public:
167
PrettyStackTraceEmit(const Record &Def, const Pattern *Pat = nullptr)
168
: Def(Def), Pat(Pat) {}
169
170
void print(raw_ostream &OS) const override {
171
if (Def.isSubClassOf("GICombineRule"))
172
OS << "Emitting GICombineRule '" << Def.getName() << "'";
173
else if (Def.isSubClassOf(PatFrag::ClassName))
174
OS << "Emitting " << PatFrag::ClassName << " '" << Def.getName() << "'";
175
else
176
OS << "Emitting '" << Def.getName() << "'";
177
178
if (Pat)
179
OS << " [" << Pat->getKindName() << " '" << Pat->getName() << "']";
180
OS << '\n';
181
}
182
};
183
184
//===- CombineRuleOperandTypeChecker --------------------------------------===//
185
186
/// This is a wrapper around OperandTypeChecker specialized for Combiner Rules.
187
/// On top of doing the same things as OperandTypeChecker, this also attempts to
188
/// infer as many types as possible for temporary register defs & immediates in
189
/// apply patterns.
190
///
191
/// The inference is trivial and leverages the MCOI OperandTypes encoded in
192
/// CodeGenInstructions to infer types across patterns in a CombineRule. It's
193
/// thus very limited and only supports CodeGenInstructions (but that's the main
194
/// use case so it's fine).
195
///
196
/// We only try to infer untyped operands in apply patterns when they're temp
197
/// reg defs, or immediates. Inference always outputs a `TypeOf<$x>` where $x is
198
/// a named operand from a match pattern.
199
class CombineRuleOperandTypeChecker : private OperandTypeChecker {
200
public:
201
CombineRuleOperandTypeChecker(const Record &RuleDef,
202
const OperandTable &MatchOpTable)
203
: OperandTypeChecker(RuleDef.getLoc()), RuleDef(RuleDef),
204
MatchOpTable(MatchOpTable) {}
205
206
/// Records and checks a 'match' pattern.
207
bool processMatchPattern(InstructionPattern &P);
208
209
/// Records and checks an 'apply' pattern.
210
bool processApplyPattern(InstructionPattern &P);
211
212
/// Propagates types, then perform type inference and do a second round of
213
/// propagation in the apply patterns only if any types were inferred.
214
void propagateAndInferTypes();
215
216
private:
217
/// TypeEquivalenceClasses are groups of operands of an instruction that share
218
/// a common type.
219
///
220
/// e.g. [[a, b], [c, d]] means a and b have the same type, and c and
221
/// d have the same type too. b/c and a/d don't have to have the same type,
222
/// though.
223
using TypeEquivalenceClasses = EquivalenceClasses<StringRef>;
224
225
/// \returns true for `OPERAND_GENERIC_` 0 through 5.
226
/// These are the MCOI types that can be registers. The other MCOI types are
227
/// either immediates, or fancier operands used only post-ISel, so we don't
228
/// care about them for combiners.
229
static bool canMCOIOperandTypeBeARegister(StringRef MCOIType) {
230
// Assume OPERAND_GENERIC_0 through 5 can be registers. The other MCOI
231
// OperandTypes are either never used in gMIR, or not relevant (e.g.
232
// OPERAND_GENERIC_IMM, which is definitely never a register).
233
return MCOIType.drop_back(1).ends_with("OPERAND_GENERIC_");
234
}
235
236
/// Finds the "MCOI::"" operand types for each operand of \p CGP.
237
///
238
/// This is a bit trickier than it looks because we need to handle variadic
239
/// in/outs.
240
///
241
/// e.g. for
242
/// (G_BUILD_VECTOR $vec, $x, $y) ->
243
/// [MCOI::OPERAND_GENERIC_0, MCOI::OPERAND_GENERIC_1,
244
/// MCOI::OPERAND_GENERIC_1]
245
///
246
/// For unknown types (which can happen in variadics where varargs types are
247
/// inconsistent), a unique name is given, e.g. "unknown_type_0".
248
static std::vector<std::string>
249
getMCOIOperandTypes(const CodeGenInstructionPattern &CGP);
250
251
/// Adds the TypeEquivalenceClasses for \p P in \p OutTECs.
252
void getInstEqClasses(const InstructionPattern &P,
253
TypeEquivalenceClasses &OutTECs) const;
254
255
/// Calls `getInstEqClasses` on all patterns of the rule to produce the whole
256
/// rule's TypeEquivalenceClasses.
257
TypeEquivalenceClasses getRuleEqClasses() const;
258
259
/// Tries to infer the type of the \p ImmOpIdx -th operand of \p IP using \p
260
/// TECs.
261
///
262
/// This is achieved by trying to find a named operand in \p IP that shares
263
/// the same type as \p ImmOpIdx, and using \ref inferNamedOperandType on that
264
/// operand instead.
265
///
266
/// \returns the inferred type or an empty PatternType if inference didn't
267
/// succeed.
268
PatternType inferImmediateType(const InstructionPattern &IP,
269
unsigned ImmOpIdx,
270
const TypeEquivalenceClasses &TECs) const;
271
272
/// Looks inside \p TECs to infer \p OpName's type.
273
///
274
/// \returns the inferred type or an empty PatternType if inference didn't
275
/// succeed.
276
PatternType inferNamedOperandType(const InstructionPattern &IP,
277
StringRef OpName,
278
const TypeEquivalenceClasses &TECs,
279
bool AllowSelf = false) const;
280
281
const Record &RuleDef;
282
SmallVector<InstructionPattern *, 8> MatchPats;
283
SmallVector<InstructionPattern *, 8> ApplyPats;
284
285
const OperandTable &MatchOpTable;
286
};
287
288
bool CombineRuleOperandTypeChecker::processMatchPattern(InstructionPattern &P) {
289
MatchPats.push_back(&P);
290
return check(P, /*CheckTypeOf*/ [](const auto &) {
291
// GITypeOf in 'match' is currently always rejected by the
292
// CombineRuleBuilder after inference is done.
293
return true;
294
});
295
}
296
297
bool CombineRuleOperandTypeChecker::processApplyPattern(InstructionPattern &P) {
298
ApplyPats.push_back(&P);
299
return check(P, /*CheckTypeOf*/ [&](const PatternType &Ty) {
300
// GITypeOf<"$x"> can only be used if "$x" is a matched operand.
301
const auto OpName = Ty.getTypeOfOpName();
302
if (MatchOpTable.lookup(OpName).Found)
303
return true;
304
305
PrintError(RuleDef.getLoc(), "'" + OpName + "' ('" + Ty.str() +
306
"') does not refer to a matched operand!");
307
return false;
308
});
309
}
310
311
void CombineRuleOperandTypeChecker::propagateAndInferTypes() {
312
/// First step here is to propagate types using the OperandTypeChecker. That
313
/// way we ensure all uses of a given register have consistent types.
314
propagateTypes();
315
316
/// Build the TypeEquivalenceClasses for the whole rule.
317
const TypeEquivalenceClasses TECs = getRuleEqClasses();
318
319
/// Look at the apply patterns and find operands that need to be
320
/// inferred. We then try to find an equivalence class that they're a part of
321
/// and select the best operand to use for the `GITypeOf` type. We prioritize
322
/// defs of matched instructions because those are guaranteed to be registers.
323
bool InferredAny = false;
324
for (auto *Pat : ApplyPats) {
325
for (unsigned K = 0; K < Pat->operands_size(); ++K) {
326
auto &Op = Pat->getOperand(K);
327
328
// We only want to take a look at untyped defs or immediates.
329
if ((!Op.isDef() && !Op.hasImmValue()) || Op.getType())
330
continue;
331
332
// Infer defs & named immediates.
333
if (Op.isDef() || Op.isNamedImmediate()) {
334
// Check it's not a redefinition of a matched operand.
335
// In such cases, inference is not necessary because we just copy
336
// operands and don't create temporary registers.
337
if (MatchOpTable.lookup(Op.getOperandName()).Found)
338
continue;
339
340
// Inference is needed here, so try to do it.
341
if (PatternType Ty =
342
inferNamedOperandType(*Pat, Op.getOperandName(), TECs)) {
343
if (DebugTypeInfer)
344
errs() << "INFER: " << Op.describe() << " -> " << Ty.str() << '\n';
345
Op.setType(Ty);
346
InferredAny = true;
347
}
348
349
continue;
350
}
351
352
// Infer immediates
353
if (Op.hasImmValue()) {
354
if (PatternType Ty = inferImmediateType(*Pat, K, TECs)) {
355
if (DebugTypeInfer)
356
errs() << "INFER: " << Op.describe() << " -> " << Ty.str() << '\n';
357
Op.setType(Ty);
358
InferredAny = true;
359
}
360
continue;
361
}
362
}
363
}
364
365
// If we've inferred any types, we want to propagate them across the apply
366
// patterns. Type inference only adds GITypeOf types that point to Matched
367
// operands, so we definitely don't want to propagate types into the match
368
// patterns as well, otherwise bad things happen.
369
if (InferredAny) {
370
OperandTypeChecker OTC(RuleDef.getLoc());
371
for (auto *Pat : ApplyPats) {
372
if (!OTC.check(*Pat, [&](const auto &) { return true; }))
373
PrintFatalError(RuleDef.getLoc(),
374
"OperandTypeChecker unexpectedly failed on '" +
375
Pat->getName() + "' during Type Inference");
376
}
377
OTC.propagateTypes();
378
379
if (DebugTypeInfer) {
380
errs() << "Apply patterns for rule " << RuleDef.getName()
381
<< " after inference:\n";
382
for (auto *Pat : ApplyPats) {
383
errs() << " ";
384
Pat->print(errs(), /*PrintName*/ true);
385
errs() << '\n';
386
}
387
errs() << '\n';
388
}
389
}
390
}
391
392
PatternType CombineRuleOperandTypeChecker::inferImmediateType(
393
const InstructionPattern &IP, unsigned ImmOpIdx,
394
const TypeEquivalenceClasses &TECs) const {
395
// We can only infer CGPs (except intrinsics).
396
const auto *CGP = dyn_cast<CodeGenInstructionPattern>(&IP);
397
if (!CGP || CGP->isIntrinsic())
398
return {};
399
400
// For CGPs, we try to infer immediates by trying to infer another named
401
// operand that shares its type.
402
//
403
// e.g.
404
// Pattern: G_BUILD_VECTOR $x, $y, 0
405
// MCOIs: [MCOI::OPERAND_GENERIC_0, MCOI::OPERAND_GENERIC_1,
406
// MCOI::OPERAND_GENERIC_1]
407
// $y has the same type as 0, so we can infer $y and get the type 0 should
408
// have.
409
410
// We infer immediates by looking for a named operand that shares the same
411
// MCOI type.
412
const auto MCOITypes = getMCOIOperandTypes(*CGP);
413
StringRef ImmOpTy = MCOITypes[ImmOpIdx];
414
415
for (const auto &[Idx, Ty] : enumerate(MCOITypes)) {
416
if (Idx != ImmOpIdx && Ty == ImmOpTy) {
417
const auto &Op = IP.getOperand(Idx);
418
if (!Op.isNamedOperand())
419
continue;
420
421
// Named operand with the same name, try to infer that.
422
if (PatternType InferTy = inferNamedOperandType(IP, Op.getOperandName(),
423
TECs, /*AllowSelf=*/true))
424
return InferTy;
425
}
426
}
427
428
return {};
429
}
430
431
PatternType CombineRuleOperandTypeChecker::inferNamedOperandType(
432
const InstructionPattern &IP, StringRef OpName,
433
const TypeEquivalenceClasses &TECs, bool AllowSelf) const {
434
// This is the simplest possible case, we just need to find a TEC that
435
// contains OpName. Look at all operands in equivalence class and try to
436
// find a suitable one. If `AllowSelf` is true, the operand itself is also
437
// considered suitable.
438
439
// Check for a def of a matched pattern. This is guaranteed to always
440
// be a register so we can blindly use that.
441
StringRef GoodOpName;
442
for (auto It = TECs.findLeader(OpName); It != TECs.member_end(); ++It) {
443
if (!AllowSelf && *It == OpName)
444
continue;
445
446
const auto LookupRes = MatchOpTable.lookup(*It);
447
if (LookupRes.Def) // Favor defs
448
return PatternType::getTypeOf(*It);
449
450
// Otherwise just save this in case we don't find any def.
451
if (GoodOpName.empty() && LookupRes.Found)
452
GoodOpName = *It;
453
}
454
455
if (!GoodOpName.empty())
456
return PatternType::getTypeOf(GoodOpName);
457
458
// No good operand found, give up.
459
return {};
460
}
461
462
std::vector<std::string> CombineRuleOperandTypeChecker::getMCOIOperandTypes(
463
const CodeGenInstructionPattern &CGP) {
464
// FIXME?: Should we cache this? We call it twice when inferring immediates.
465
466
static unsigned UnknownTypeIdx = 0;
467
468
std::vector<std::string> OpTypes;
469
auto &CGI = CGP.getInst();
470
Record *VarArgsTy = CGI.TheDef->isSubClassOf("GenericInstruction")
471
? CGI.TheDef->getValueAsOptionalDef("variadicOpsType")
472
: nullptr;
473
std::string VarArgsTyName =
474
VarArgsTy ? ("MCOI::" + VarArgsTy->getValueAsString("OperandType")).str()
475
: ("unknown_type_" + Twine(UnknownTypeIdx++)).str();
476
477
// First, handle defs.
478
for (unsigned K = 0; K < CGI.Operands.NumDefs; ++K)
479
OpTypes.push_back(CGI.Operands[K].OperandType);
480
481
// Then, handle variadic defs if there are any.
482
if (CGP.hasVariadicDefs()) {
483
for (unsigned K = CGI.Operands.NumDefs; K < CGP.getNumInstDefs(); ++K)
484
OpTypes.push_back(VarArgsTyName);
485
}
486
487
// If we had variadic defs, the op idx in the pattern won't match the op idx
488
// in the CGI anymore.
489
int CGIOpOffset = int(CGI.Operands.NumDefs) - CGP.getNumInstDefs();
490
assert(CGP.hasVariadicDefs() ? (CGIOpOffset <= 0) : (CGIOpOffset == 0));
491
492
// Handle all remaining use operands, including variadic ones.
493
for (unsigned K = CGP.getNumInstDefs(); K < CGP.getNumInstOperands(); ++K) {
494
unsigned CGIOpIdx = K + CGIOpOffset;
495
if (CGIOpIdx >= CGI.Operands.size()) {
496
assert(CGP.isVariadic());
497
OpTypes.push_back(VarArgsTyName);
498
} else {
499
OpTypes.push_back(CGI.Operands[CGIOpIdx].OperandType);
500
}
501
}
502
503
assert(OpTypes.size() == CGP.operands_size());
504
return OpTypes;
505
}
506
507
void CombineRuleOperandTypeChecker::getInstEqClasses(
508
const InstructionPattern &P, TypeEquivalenceClasses &OutTECs) const {
509
// Determine the TypeEquivalenceClasses by:
510
// - Getting the MCOI Operand Types.
511
// - Creating a Map of MCOI Type -> [Operand Indexes]
512
// - Iterating over the map, filtering types we don't like, and just adding
513
// the array of Operand Indexes to \p OutTECs.
514
515
// We can only do this on CodeGenInstructions that aren't intrinsics. Other
516
// InstructionPatterns have no type inference information associated with
517
// them.
518
// TODO: We could try to extract some info from CodeGenIntrinsic to
519
// guide inference.
520
521
// TODO: Could we add some inference information to builtins at least? e.g.
522
// ReplaceReg should always replace with a reg of the same type, for instance.
523
// Though, those patterns are often used alone so it might not be worth the
524
// trouble to infer their types.
525
auto *CGP = dyn_cast<CodeGenInstructionPattern>(&P);
526
if (!CGP || CGP->isIntrinsic())
527
return;
528
529
const auto MCOITypes = getMCOIOperandTypes(*CGP);
530
assert(MCOITypes.size() == P.operands_size());
531
532
MapVector<StringRef, SmallVector<unsigned, 0>> TyToOpIdx;
533
for (const auto &[Idx, Ty] : enumerate(MCOITypes))
534
TyToOpIdx[Ty].push_back(Idx);
535
536
if (DebugTypeInfer)
537
errs() << "\tGroups for " << P.getName() << ":\t";
538
539
for (const auto &[Ty, Idxs] : TyToOpIdx) {
540
if (!canMCOIOperandTypeBeARegister(Ty))
541
continue;
542
543
if (DebugTypeInfer)
544
errs() << '[';
545
StringRef Sep = "";
546
547
// We only collect named operands.
548
StringRef Leader;
549
for (unsigned Idx : Idxs) {
550
const auto &Op = P.getOperand(Idx);
551
if (!Op.isNamedOperand())
552
continue;
553
554
const auto OpName = Op.getOperandName();
555
if (DebugTypeInfer) {
556
errs() << Sep << OpName;
557
Sep = ", ";
558
}
559
560
if (Leader.empty())
561
OutTECs.insert((Leader = OpName));
562
else
563
OutTECs.unionSets(Leader, OpName);
564
}
565
566
if (DebugTypeInfer)
567
errs() << "] ";
568
}
569
570
if (DebugTypeInfer)
571
errs() << '\n';
572
}
573
574
CombineRuleOperandTypeChecker::TypeEquivalenceClasses
575
CombineRuleOperandTypeChecker::getRuleEqClasses() const {
576
StringMap<unsigned> OpNameToEqClassIdx;
577
TypeEquivalenceClasses TECs;
578
579
if (DebugTypeInfer)
580
errs() << "Rule Operand Type Equivalence Classes for " << RuleDef.getName()
581
<< ":\n";
582
583
for (const auto *Pat : MatchPats)
584
getInstEqClasses(*Pat, TECs);
585
for (const auto *Pat : ApplyPats)
586
getInstEqClasses(*Pat, TECs);
587
588
if (DebugTypeInfer) {
589
errs() << "Final Type Equivalence Classes: ";
590
for (auto ClassIt = TECs.begin(); ClassIt != TECs.end(); ++ClassIt) {
591
// only print non-empty classes.
592
if (auto MembIt = TECs.member_begin(ClassIt);
593
MembIt != TECs.member_end()) {
594
errs() << '[';
595
StringRef Sep = "";
596
for (; MembIt != TECs.member_end(); ++MembIt) {
597
errs() << Sep << *MembIt;
598
Sep = ", ";
599
}
600
errs() << "] ";
601
}
602
}
603
errs() << '\n';
604
}
605
606
return TECs;
607
}
608
609
//===- MatchData Handling -------------------------------------------------===//
610
struct MatchDataDef {
611
MatchDataDef(StringRef Symbol, StringRef Type) : Symbol(Symbol), Type(Type) {}
612
613
StringRef Symbol;
614
StringRef Type;
615
616
/// \returns the desired variable name for this MatchData.
617
std::string getVarName() const {
618
// Add a prefix in case the symbol name is very generic and conflicts with
619
// something else.
620
return "GIMatchData_" + Symbol.str();
621
}
622
};
623
624
//===- CombineRuleBuilder -------------------------------------------------===//
625
626
/// Parses combine rule and builds a small intermediate representation to tie
627
/// patterns together and emit RuleMatchers to match them. This may emit more
628
/// than one RuleMatcher, e.g. for `wip_match_opcode`.
629
///
630
/// Memory management for `Pattern` objects is done through `std::unique_ptr`.
631
/// In most cases, there are two stages to a pattern's lifetime:
632
/// - Creation in a `parse` function
633
/// - The unique_ptr is stored in a variable, and may be destroyed if the
634
/// pattern is found to be semantically invalid.
635
/// - Ownership transfer into a `PatternMap`
636
/// - Once a pattern is moved into either the map of Match or Apply
637
/// patterns, it is known to be valid and it never moves back.
638
class CombineRuleBuilder {
639
public:
640
using PatternMap = MapVector<StringRef, std::unique_ptr<Pattern>>;
641
using PatternAlternatives = DenseMap<const Pattern *, unsigned>;
642
643
CombineRuleBuilder(const CodeGenTarget &CGT,
644
SubtargetFeatureInfoMap &SubtargetFeatures,
645
Record &RuleDef, unsigned ID,
646
std::vector<RuleMatcher> &OutRMs)
647
: Parser(CGT, RuleDef.getLoc()), CGT(CGT),
648
SubtargetFeatures(SubtargetFeatures), RuleDef(RuleDef), RuleID(ID),
649
OutRMs(OutRMs) {}
650
651
/// Parses all fields in the RuleDef record.
652
bool parseAll();
653
654
/// Emits all RuleMatchers into the vector of RuleMatchers passed in the
655
/// constructor.
656
bool emitRuleMatchers();
657
658
void print(raw_ostream &OS) const;
659
void dump() const { print(dbgs()); }
660
661
/// Debug-only verification of invariants.
662
#ifndef NDEBUG
663
void verify() const;
664
#endif
665
666
private:
667
const CodeGenInstruction &getGConstant() const {
668
return CGT.getInstruction(RuleDef.getRecords().getDef("G_CONSTANT"));
669
}
670
671
void PrintError(Twine Msg) const { ::PrintError(&RuleDef, Msg); }
672
void PrintWarning(Twine Msg) const { ::PrintWarning(RuleDef.getLoc(), Msg); }
673
void PrintNote(Twine Msg) const { ::PrintNote(RuleDef.getLoc(), Msg); }
674
675
void print(raw_ostream &OS, const PatternAlternatives &Alts) const;
676
677
bool addApplyPattern(std::unique_ptr<Pattern> Pat);
678
bool addMatchPattern(std::unique_ptr<Pattern> Pat);
679
680
/// Adds the expansions from \see MatchDatas to \p CE.
681
void declareAllMatchDatasExpansions(CodeExpansions &CE) const;
682
683
/// Adds a matcher \p P to \p IM, expanding its code using \p CE.
684
/// Note that the predicate is added on the last InstructionMatcher.
685
///
686
/// \p Alts is only used if DebugCXXPreds is enabled.
687
void addCXXPredicate(RuleMatcher &M, const CodeExpansions &CE,
688
const CXXPattern &P, const PatternAlternatives &Alts);
689
690
bool hasOnlyCXXApplyPatterns() const;
691
bool hasEraseRoot() const;
692
693
// Infer machine operand types and check their consistency.
694
bool typecheckPatterns();
695
696
/// For all PatFragPatterns, add a new entry in PatternAlternatives for each
697
/// PatternList it contains. This is multiplicative, so if we have 2
698
/// PatFrags with 3 alternatives each, we get 2*3 permutations added to
699
/// PermutationsToEmit. The "MaxPermutations" field controls how many
700
/// permutations are allowed before an error is emitted and this function
701
/// returns false. This is a simple safeguard to prevent combination of
702
/// PatFrags from generating enormous amounts of rules.
703
bool buildPermutationsToEmit();
704
705
/// Checks additional semantics of the Patterns.
706
bool checkSemantics();
707
708
/// Creates a new RuleMatcher with some boilerplate
709
/// settings/actions/predicates, and and adds it to \p OutRMs.
710
/// \see addFeaturePredicates too.
711
///
712
/// \param Alts Current set of alternatives, for debug comment.
713
/// \param AdditionalComment Comment string to be added to the
714
/// `DebugCommentAction`.
715
RuleMatcher &addRuleMatcher(const PatternAlternatives &Alts,
716
Twine AdditionalComment = "");
717
bool addFeaturePredicates(RuleMatcher &M);
718
719
bool findRoots();
720
bool buildRuleOperandsTable();
721
722
bool parseDefs(const DagInit &Def);
723
724
bool emitMatchPattern(CodeExpansions &CE, const PatternAlternatives &Alts,
725
const InstructionPattern &IP);
726
bool emitMatchPattern(CodeExpansions &CE, const PatternAlternatives &Alts,
727
const AnyOpcodePattern &AOP);
728
729
bool emitPatFragMatchPattern(CodeExpansions &CE,
730
const PatternAlternatives &Alts, RuleMatcher &RM,
731
InstructionMatcher *IM,
732
const PatFragPattern &PFP,
733
DenseSet<const Pattern *> &SeenPats);
734
735
bool emitApplyPatterns(CodeExpansions &CE, RuleMatcher &M);
736
bool emitCXXMatchApply(CodeExpansions &CE, RuleMatcher &M,
737
ArrayRef<CXXPattern *> Matchers);
738
739
// Recursively visits InstructionPatterns from P to build up the
740
// RuleMatcher actions.
741
bool emitInstructionApplyPattern(CodeExpansions &CE, RuleMatcher &M,
742
const InstructionPattern &P,
743
DenseSet<const Pattern *> &SeenPats,
744
StringMap<unsigned> &OperandToTempRegID);
745
746
bool emitCodeGenInstructionApplyImmOperand(RuleMatcher &M,
747
BuildMIAction &DstMI,
748
const CodeGenInstructionPattern &P,
749
const InstructionOperand &O);
750
751
bool emitBuiltinApplyPattern(CodeExpansions &CE, RuleMatcher &M,
752
const BuiltinPattern &P,
753
StringMap<unsigned> &OperandToTempRegID);
754
755
// Recursively visits CodeGenInstructionPattern from P to build up the
756
// RuleMatcher/InstructionMatcher. May create new InstructionMatchers as
757
// needed.
758
using OperandMapperFnRef =
759
function_ref<InstructionOperand(const InstructionOperand &)>;
760
using OperandDefLookupFn =
761
function_ref<const InstructionPattern *(StringRef)>;
762
bool emitCodeGenInstructionMatchPattern(
763
CodeExpansions &CE, const PatternAlternatives &Alts, RuleMatcher &M,
764
InstructionMatcher &IM, const CodeGenInstructionPattern &P,
765
DenseSet<const Pattern *> &SeenPats, OperandDefLookupFn LookupOperandDef,
766
OperandMapperFnRef OperandMapper = [](const auto &O) { return O; });
767
768
PatternParser Parser;
769
const CodeGenTarget &CGT;
770
SubtargetFeatureInfoMap &SubtargetFeatures;
771
Record &RuleDef;
772
const unsigned RuleID;
773
std::vector<RuleMatcher> &OutRMs;
774
775
// For InstructionMatcher::addOperand
776
unsigned AllocatedTemporariesBaseID = 0;
777
778
/// The root of the pattern.
779
StringRef RootName;
780
781
/// These maps have ownership of the actual Pattern objects.
782
/// They both map a Pattern's name to the Pattern instance.
783
PatternMap MatchPats;
784
PatternMap ApplyPats;
785
786
/// Operand tables to tie match/apply patterns together.
787
OperandTable MatchOpTable;
788
OperandTable ApplyOpTable;
789
790
/// Set by findRoots.
791
Pattern *MatchRoot = nullptr;
792
SmallDenseSet<InstructionPattern *, 2> ApplyRoots;
793
794
SmallVector<MatchDataDef, 2> MatchDatas;
795
SmallVector<PatternAlternatives, 1> PermutationsToEmit;
796
};
797
798
bool CombineRuleBuilder::parseAll() {
799
auto StackTrace = PrettyStackTraceParse(RuleDef);
800
801
if (!parseDefs(*RuleDef.getValueAsDag("Defs")))
802
return false;
803
804
if (!Parser.parsePatternList(
805
*RuleDef.getValueAsDag("Match"),
806
[this](auto Pat) { return addMatchPattern(std::move(Pat)); }, "match",
807
(RuleDef.getName() + "_match").str()))
808
return false;
809
810
if (!Parser.parsePatternList(
811
*RuleDef.getValueAsDag("Apply"),
812
[this](auto Pat) { return addApplyPattern(std::move(Pat)); }, "apply",
813
(RuleDef.getName() + "_apply").str()))
814
return false;
815
816
if (!buildRuleOperandsTable() || !typecheckPatterns() || !findRoots() ||
817
!checkSemantics() || !buildPermutationsToEmit())
818
return false;
819
LLVM_DEBUG(verify());
820
return true;
821
}
822
823
bool CombineRuleBuilder::emitRuleMatchers() {
824
auto StackTrace = PrettyStackTraceEmit(RuleDef);
825
826
assert(MatchRoot);
827
CodeExpansions CE;
828
829
assert(!PermutationsToEmit.empty());
830
for (const auto &Alts : PermutationsToEmit) {
831
switch (MatchRoot->getKind()) {
832
case Pattern::K_AnyOpcode: {
833
if (!emitMatchPattern(CE, Alts, *cast<AnyOpcodePattern>(MatchRoot)))
834
return false;
835
break;
836
}
837
case Pattern::K_PatFrag:
838
case Pattern::K_Builtin:
839
case Pattern::K_CodeGenInstruction:
840
if (!emitMatchPattern(CE, Alts, *cast<InstructionPattern>(MatchRoot)))
841
return false;
842
break;
843
case Pattern::K_CXX:
844
PrintError("C++ code cannot be the root of a rule!");
845
return false;
846
default:
847
llvm_unreachable("unknown pattern kind!");
848
}
849
}
850
851
return true;
852
}
853
854
void CombineRuleBuilder::print(raw_ostream &OS) const {
855
OS << "(CombineRule name:" << RuleDef.getName() << " id:" << RuleID
856
<< " root:" << RootName << '\n';
857
858
if (!MatchDatas.empty()) {
859
OS << " (MatchDatas\n";
860
for (const auto &MD : MatchDatas) {
861
OS << " (MatchDataDef symbol:" << MD.Symbol << " type:" << MD.Type
862
<< ")\n";
863
}
864
OS << " )\n";
865
}
866
867
const auto &SeenPFs = Parser.getSeenPatFrags();
868
if (!SeenPFs.empty()) {
869
OS << " (PatFrags\n";
870
for (const auto *PF : Parser.getSeenPatFrags()) {
871
PF->print(OS, /*Indent=*/" ");
872
OS << '\n';
873
}
874
OS << " )\n";
875
}
876
877
const auto DumpPats = [&](StringRef Name, const PatternMap &Pats) {
878
OS << " (" << Name << " ";
879
if (Pats.empty()) {
880
OS << "<empty>)\n";
881
return;
882
}
883
884
OS << '\n';
885
for (const auto &[Name, Pat] : Pats) {
886
OS << " ";
887
if (Pat.get() == MatchRoot)
888
OS << "<match_root>";
889
if (isa<InstructionPattern>(Pat.get()) &&
890
ApplyRoots.contains(cast<InstructionPattern>(Pat.get())))
891
OS << "<apply_root>";
892
OS << Name << ":";
893
Pat->print(OS, /*PrintName=*/false);
894
OS << '\n';
895
}
896
OS << " )\n";
897
};
898
899
DumpPats("MatchPats", MatchPats);
900
DumpPats("ApplyPats", ApplyPats);
901
902
MatchOpTable.print(OS, "MatchPats", /*Indent*/ " ");
903
ApplyOpTable.print(OS, "ApplyPats", /*Indent*/ " ");
904
905
if (PermutationsToEmit.size() > 1) {
906
OS << " (PermutationsToEmit\n";
907
for (const auto &Perm : PermutationsToEmit) {
908
OS << " ";
909
print(OS, Perm);
910
OS << ",\n";
911
}
912
OS << " )\n";
913
}
914
915
OS << ")\n";
916
}
917
918
#ifndef NDEBUG
919
void CombineRuleBuilder::verify() const {
920
const auto VerifyPats = [&](const PatternMap &Pats) {
921
for (const auto &[Name, Pat] : Pats) {
922
if (!Pat)
923
PrintFatalError("null pattern in pattern map!");
924
925
if (Name != Pat->getName()) {
926
Pat->dump();
927
PrintFatalError("Pattern name mismatch! Map name: " + Name +
928
", Pat name: " + Pat->getName());
929
}
930
931
// Sanity check: the map should point to the same data as the Pattern.
932
// Both strings are allocated in the pool using insertStrRef.
933
if (Name.data() != Pat->getName().data()) {
934
dbgs() << "Map StringRef: '" << Name << "' @ "
935
<< (const void *)Name.data() << '\n';
936
dbgs() << "Pat String: '" << Pat->getName() << "' @ "
937
<< (const void *)Pat->getName().data() << '\n';
938
PrintFatalError("StringRef stored in the PatternMap is not referencing "
939
"the same string as its Pattern!");
940
}
941
}
942
};
943
944
VerifyPats(MatchPats);
945
VerifyPats(ApplyPats);
946
947
// Check there are no wip_match_opcode patterns in the "apply" patterns.
948
if (any_of(ApplyPats,
949
[&](auto &E) { return isa<AnyOpcodePattern>(E.second.get()); })) {
950
dump();
951
PrintFatalError(
952
"illegal wip_match_opcode pattern in the 'apply' patterns!");
953
}
954
955
// Check there are no nullptrs in ApplyRoots.
956
if (ApplyRoots.contains(nullptr)) {
957
PrintFatalError(
958
"CombineRuleBuilder's ApplyRoots set contains a null pointer!");
959
}
960
}
961
#endif
962
963
void CombineRuleBuilder::print(raw_ostream &OS,
964
const PatternAlternatives &Alts) const {
965
SmallVector<std::string, 1> Strings(
966
map_range(Alts, [](const auto &PatAndPerm) {
967
return PatAndPerm.first->getName().str() + "[" +
968
to_string(PatAndPerm.second) + "]";
969
}));
970
// Sort so output is deterministic for tests. Otherwise it's sorted by pointer
971
// values.
972
sort(Strings);
973
OS << "[" << join(Strings, ", ") << "]";
974
}
975
976
bool CombineRuleBuilder::addApplyPattern(std::unique_ptr<Pattern> Pat) {
977
StringRef Name = Pat->getName();
978
if (ApplyPats.contains(Name)) {
979
PrintError("'" + Name + "' apply pattern defined more than once!");
980
return false;
981
}
982
983
if (isa<AnyOpcodePattern>(Pat.get())) {
984
PrintError("'" + Name +
985
"': wip_match_opcode is not supported in apply patterns");
986
return false;
987
}
988
989
if (isa<PatFragPattern>(Pat.get())) {
990
PrintError("'" + Name + "': using " + PatFrag::ClassName +
991
" is not supported in apply patterns");
992
return false;
993
}
994
995
if (auto *CXXPat = dyn_cast<CXXPattern>(Pat.get()))
996
CXXPat->setIsApply();
997
998
ApplyPats[Name] = std::move(Pat);
999
return true;
1000
}
1001
1002
bool CombineRuleBuilder::addMatchPattern(std::unique_ptr<Pattern> Pat) {
1003
StringRef Name = Pat->getName();
1004
if (MatchPats.contains(Name)) {
1005
PrintError("'" + Name + "' match pattern defined more than once!");
1006
return false;
1007
}
1008
1009
// For now, none of the builtins can appear in 'match'.
1010
if (const auto *BP = dyn_cast<BuiltinPattern>(Pat.get())) {
1011
PrintError("'" + BP->getInstName() +
1012
"' cannot be used in a 'match' pattern");
1013
return false;
1014
}
1015
1016
MatchPats[Name] = std::move(Pat);
1017
return true;
1018
}
1019
1020
void CombineRuleBuilder::declareAllMatchDatasExpansions(
1021
CodeExpansions &CE) const {
1022
for (const auto &MD : MatchDatas)
1023
CE.declare(MD.Symbol, MD.getVarName());
1024
}
1025
1026
void CombineRuleBuilder::addCXXPredicate(RuleMatcher &M,
1027
const CodeExpansions &CE,
1028
const CXXPattern &P,
1029
const PatternAlternatives &Alts) {
1030
// FIXME: Hack so C++ code is executed last. May not work for more complex
1031
// patterns.
1032
auto &IM = *std::prev(M.insnmatchers().end());
1033
auto Loc = RuleDef.getLoc();
1034
const auto AddComment = [&](raw_ostream &OS) {
1035
OS << "// Pattern Alternatives: ";
1036
print(OS, Alts);
1037
OS << '\n';
1038
};
1039
const auto &ExpandedCode =
1040
DebugCXXPreds ? P.expandCode(CE, Loc, AddComment) : P.expandCode(CE, Loc);
1041
IM->addPredicate<GenericInstructionPredicateMatcher>(
1042
ExpandedCode.getEnumNameWithPrefix(CXXPredPrefix));
1043
}
1044
1045
bool CombineRuleBuilder::hasOnlyCXXApplyPatterns() const {
1046
return all_of(ApplyPats, [&](auto &Entry) {
1047
return isa<CXXPattern>(Entry.second.get());
1048
});
1049
}
1050
1051
bool CombineRuleBuilder::hasEraseRoot() const {
1052
return any_of(ApplyPats, [&](auto &Entry) {
1053
if (const auto *BP = dyn_cast<BuiltinPattern>(Entry.second.get()))
1054
return BP->getBuiltinKind() == BI_EraseRoot;
1055
return false;
1056
});
1057
}
1058
1059
bool CombineRuleBuilder::typecheckPatterns() {
1060
CombineRuleOperandTypeChecker OTC(RuleDef, MatchOpTable);
1061
1062
for (auto &Pat : values(MatchPats)) {
1063
if (auto *IP = dyn_cast<InstructionPattern>(Pat.get())) {
1064
if (!OTC.processMatchPattern(*IP))
1065
return false;
1066
}
1067
}
1068
1069
for (auto &Pat : values(ApplyPats)) {
1070
if (auto *IP = dyn_cast<InstructionPattern>(Pat.get())) {
1071
if (!OTC.processApplyPattern(*IP))
1072
return false;
1073
}
1074
}
1075
1076
OTC.propagateAndInferTypes();
1077
1078
// Always check this after in case inference adds some special types to the
1079
// match patterns.
1080
for (auto &Pat : values(MatchPats)) {
1081
if (auto *IP = dyn_cast<InstructionPattern>(Pat.get())) {
1082
if (IP->diagnoseAllSpecialTypes(
1083
RuleDef.getLoc(), PatternType::SpecialTyClassName +
1084
" is not supported in 'match' patterns")) {
1085
return false;
1086
}
1087
}
1088
}
1089
return true;
1090
}
1091
1092
bool CombineRuleBuilder::buildPermutationsToEmit() {
1093
PermutationsToEmit.clear();
1094
1095
// Start with one empty set of alternatives.
1096
PermutationsToEmit.emplace_back();
1097
for (const auto &Pat : values(MatchPats)) {
1098
unsigned NumAlts = 0;
1099
// Note: technically, AnyOpcodePattern also needs permutations, but:
1100
// - We only allow a single one of them in the root.
1101
// - They cannot be mixed with any other pattern other than C++ code.
1102
// So we don't really need to take them into account here. We could, but
1103
// that pattern is a hack anyway and the less it's involved, the better.
1104
if (const auto *PFP = dyn_cast<PatFragPattern>(Pat.get()))
1105
NumAlts = PFP->getPatFrag().num_alternatives();
1106
else
1107
continue;
1108
1109
// For each pattern that needs permutations, multiply the current set of
1110
// alternatives.
1111
auto CurPerms = PermutationsToEmit;
1112
PermutationsToEmit.clear();
1113
1114
for (const auto &Perm : CurPerms) {
1115
assert(!Perm.count(Pat.get()) && "Pattern already emitted?");
1116
for (unsigned K = 0; K < NumAlts; ++K) {
1117
PatternAlternatives NewPerm = Perm;
1118
NewPerm[Pat.get()] = K;
1119
PermutationsToEmit.emplace_back(std::move(NewPerm));
1120
}
1121
}
1122
}
1123
1124
if (int64_t MaxPerms = RuleDef.getValueAsInt("MaxPermutations");
1125
MaxPerms > 0) {
1126
if ((int64_t)PermutationsToEmit.size() > MaxPerms) {
1127
PrintError("cannot emit rule '" + RuleDef.getName() + "'; " +
1128
Twine(PermutationsToEmit.size()) +
1129
" permutations would be emitted, but the max is " +
1130
Twine(MaxPerms));
1131
return false;
1132
}
1133
}
1134
1135
// Ensure we always have a single empty entry, it simplifies the emission
1136
// logic so it doesn't need to handle the case where there are no perms.
1137
if (PermutationsToEmit.empty()) {
1138
PermutationsToEmit.emplace_back();
1139
return true;
1140
}
1141
1142
return true;
1143
}
1144
1145
bool CombineRuleBuilder::checkSemantics() {
1146
assert(MatchRoot && "Cannot call this before findRoots()");
1147
1148
bool UsesWipMatchOpcode = false;
1149
for (const auto &Match : MatchPats) {
1150
const auto *Pat = Match.second.get();
1151
1152
if (const auto *CXXPat = dyn_cast<CXXPattern>(Pat)) {
1153
if (!CXXPat->getRawCode().contains("return "))
1154
PrintWarning("'match' C++ code does not seem to return!");
1155
continue;
1156
}
1157
1158
// MIFlags in match cannot use the following syntax: (MIFlags $mi)
1159
if (const auto *CGP = dyn_cast<CodeGenInstructionPattern>(Pat)) {
1160
if (auto *FI = CGP->getMIFlagsInfo()) {
1161
if (!FI->copy_flags().empty()) {
1162
PrintError(
1163
"'match' patterns cannot refer to flags from other instructions");
1164
PrintNote("MIFlags in '" + CGP->getName() +
1165
"' refer to: " + join(FI->copy_flags(), ", "));
1166
return false;
1167
}
1168
}
1169
}
1170
1171
const auto *AOP = dyn_cast<AnyOpcodePattern>(Pat);
1172
if (!AOP)
1173
continue;
1174
1175
if (UsesWipMatchOpcode) {
1176
PrintError("wip_opcode_match can only be present once");
1177
return false;
1178
}
1179
1180
UsesWipMatchOpcode = true;
1181
}
1182
1183
std::optional<bool> IsUsingCXXPatterns;
1184
for (const auto &Apply : ApplyPats) {
1185
Pattern *Pat = Apply.second.get();
1186
if (IsUsingCXXPatterns) {
1187
if (*IsUsingCXXPatterns != isa<CXXPattern>(Pat)) {
1188
PrintError("'apply' patterns cannot mix C++ code with other types of "
1189
"patterns");
1190
return false;
1191
}
1192
} else
1193
IsUsingCXXPatterns = isa<CXXPattern>(Pat);
1194
1195
assert(Pat);
1196
const auto *IP = dyn_cast<InstructionPattern>(Pat);
1197
if (!IP)
1198
continue;
1199
1200
if (UsesWipMatchOpcode) {
1201
PrintError("cannot use wip_match_opcode in combination with apply "
1202
"instruction patterns!");
1203
return false;
1204
}
1205
1206
// Check that the insts mentioned in copy_flags exist.
1207
if (const auto *CGP = dyn_cast<CodeGenInstructionPattern>(IP)) {
1208
if (auto *FI = CGP->getMIFlagsInfo()) {
1209
for (auto InstName : FI->copy_flags()) {
1210
auto It = MatchPats.find(InstName);
1211
if (It == MatchPats.end()) {
1212
PrintError("unknown instruction '$" + InstName +
1213
"' referenced in MIFlags of '" + CGP->getName() + "'");
1214
return false;
1215
}
1216
1217
if (!isa<CodeGenInstructionPattern>(It->second.get())) {
1218
PrintError(
1219
"'$" + InstName +
1220
"' does not refer to a CodeGenInstruction in MIFlags of '" +
1221
CGP->getName() + "'");
1222
return false;
1223
}
1224
}
1225
}
1226
}
1227
1228
const auto *BIP = dyn_cast<BuiltinPattern>(IP);
1229
if (!BIP)
1230
continue;
1231
StringRef Name = BIP->getInstName();
1232
1233
// (GIEraseInst) has to be the only apply pattern, or it can not be used at
1234
// all. The root cannot have any defs either.
1235
switch (BIP->getBuiltinKind()) {
1236
case BI_EraseRoot: {
1237
if (ApplyPats.size() > 1) {
1238
PrintError(Name + " must be the only 'apply' pattern");
1239
return false;
1240
}
1241
1242
const auto *IRoot = dyn_cast<CodeGenInstructionPattern>(MatchRoot);
1243
if (!IRoot) {
1244
PrintError(Name + " can only be used if the root is a "
1245
"CodeGenInstruction or Intrinsic");
1246
return false;
1247
}
1248
1249
if (IRoot->getNumInstDefs() != 0) {
1250
PrintError(Name + " can only be used if on roots that do "
1251
"not have any output operand");
1252
PrintNote("'" + IRoot->getInstName() + "' has " +
1253
Twine(IRoot->getNumInstDefs()) + " output operands");
1254
return false;
1255
}
1256
break;
1257
}
1258
case BI_ReplaceReg: {
1259
// (GIReplaceReg can only be used on the root instruction)
1260
// TODO: When we allow rewriting non-root instructions, also allow this.
1261
StringRef OldRegName = BIP->getOperand(0).getOperandName();
1262
auto *Def = MatchOpTable.getDef(OldRegName);
1263
if (!Def) {
1264
PrintError(Name + " cannot find a matched pattern that defines '" +
1265
OldRegName + "'");
1266
return false;
1267
}
1268
if (MatchOpTable.getDef(OldRegName) != MatchRoot) {
1269
PrintError(Name + " cannot replace '" + OldRegName +
1270
"': this builtin can only replace a register defined by the "
1271
"match root");
1272
return false;
1273
}
1274
break;
1275
}
1276
}
1277
}
1278
1279
if (!hasOnlyCXXApplyPatterns() && !MatchDatas.empty()) {
1280
PrintError(MatchDataClassName +
1281
" can only be used if 'apply' in entirely written in C++");
1282
return false;
1283
}
1284
1285
return true;
1286
}
1287
1288
RuleMatcher &CombineRuleBuilder::addRuleMatcher(const PatternAlternatives &Alts,
1289
Twine AdditionalComment) {
1290
auto &RM = OutRMs.emplace_back(RuleDef.getLoc());
1291
addFeaturePredicates(RM);
1292
RM.setPermanentGISelFlags(GISF_IgnoreCopies);
1293
RM.addRequiredSimplePredicate(getIsEnabledPredicateEnumName(RuleID));
1294
1295
std::string Comment;
1296
raw_string_ostream CommentOS(Comment);
1297
CommentOS << "Combiner Rule #" << RuleID << ": " << RuleDef.getName();
1298
if (!Alts.empty()) {
1299
CommentOS << " @ ";
1300
print(CommentOS, Alts);
1301
}
1302
if (!AdditionalComment.isTriviallyEmpty())
1303
CommentOS << "; " << AdditionalComment;
1304
RM.addAction<DebugCommentAction>(Comment);
1305
return RM;
1306
}
1307
1308
bool CombineRuleBuilder::addFeaturePredicates(RuleMatcher &M) {
1309
if (!RuleDef.getValue("Predicates"))
1310
return true;
1311
1312
ListInit *Preds = RuleDef.getValueAsListInit("Predicates");
1313
for (Init *PI : Preds->getValues()) {
1314
DefInit *Pred = dyn_cast<DefInit>(PI);
1315
if (!Pred)
1316
continue;
1317
1318
Record *Def = Pred->getDef();
1319
if (!Def->isSubClassOf("Predicate")) {
1320
::PrintError(Def, "Unknown 'Predicate' Type");
1321
return false;
1322
}
1323
1324
if (Def->getValueAsString("CondString").empty())
1325
continue;
1326
1327
if (SubtargetFeatures.count(Def) == 0) {
1328
SubtargetFeatures.emplace(
1329
Def, SubtargetFeatureInfo(Def, SubtargetFeatures.size()));
1330
}
1331
1332
M.addRequiredFeature(Def);
1333
}
1334
1335
return true;
1336
}
1337
1338
bool CombineRuleBuilder::findRoots() {
1339
const auto Finish = [&]() {
1340
assert(MatchRoot);
1341
1342
if (hasOnlyCXXApplyPatterns() || hasEraseRoot())
1343
return true;
1344
1345
auto *IPRoot = dyn_cast<InstructionPattern>(MatchRoot);
1346
if (!IPRoot)
1347
return true;
1348
1349
if (IPRoot->getNumInstDefs() == 0) {
1350
// No defs to work with -> find the root using the pattern name.
1351
auto It = ApplyPats.find(RootName);
1352
if (It == ApplyPats.end()) {
1353
PrintError("Cannot find root '" + RootName + "' in apply patterns!");
1354
return false;
1355
}
1356
1357
auto *ApplyRoot = dyn_cast<InstructionPattern>(It->second.get());
1358
if (!ApplyRoot) {
1359
PrintError("apply pattern root '" + RootName +
1360
"' must be an instruction pattern");
1361
return false;
1362
}
1363
1364
ApplyRoots.insert(ApplyRoot);
1365
return true;
1366
}
1367
1368
// Collect all redefinitions of the MatchRoot's defs and put them in
1369
// ApplyRoots.
1370
const auto DefsNeeded = IPRoot->getApplyDefsNeeded();
1371
for (auto &Op : DefsNeeded) {
1372
assert(Op.isDef() && Op.isNamedOperand());
1373
StringRef Name = Op.getOperandName();
1374
1375
auto *ApplyRedef = ApplyOpTable.getDef(Name);
1376
if (!ApplyRedef) {
1377
PrintError("'" + Name + "' must be redefined in the 'apply' pattern");
1378
return false;
1379
}
1380
1381
ApplyRoots.insert((InstructionPattern *)ApplyRedef);
1382
}
1383
1384
if (auto It = ApplyPats.find(RootName); It != ApplyPats.end()) {
1385
if (find(ApplyRoots, It->second.get()) == ApplyRoots.end()) {
1386
PrintError("apply pattern '" + RootName +
1387
"' is supposed to be a root but it does not redefine any of "
1388
"the defs of the match root");
1389
return false;
1390
}
1391
}
1392
1393
return true;
1394
};
1395
1396
// Look by pattern name, e.g.
1397
// (G_FNEG $x, $y):$root
1398
if (auto MatchPatIt = MatchPats.find(RootName);
1399
MatchPatIt != MatchPats.end()) {
1400
MatchRoot = MatchPatIt->second.get();
1401
return Finish();
1402
}
1403
1404
// Look by def:
1405
// (G_FNEG $root, $y)
1406
auto LookupRes = MatchOpTable.lookup(RootName);
1407
if (!LookupRes.Found) {
1408
PrintError("Cannot find root '" + RootName + "' in match patterns!");
1409
return false;
1410
}
1411
1412
MatchRoot = LookupRes.Def;
1413
if (!MatchRoot) {
1414
PrintError("Cannot use live-in operand '" + RootName +
1415
"' as match pattern root!");
1416
return false;
1417
}
1418
1419
return Finish();
1420
}
1421
1422
bool CombineRuleBuilder::buildRuleOperandsTable() {
1423
const auto DiagnoseRedefMatch = [&](StringRef OpName) {
1424
PrintError("Operand '" + OpName +
1425
"' is defined multiple times in the 'match' patterns");
1426
};
1427
1428
const auto DiagnoseRedefApply = [&](StringRef OpName) {
1429
PrintError("Operand '" + OpName +
1430
"' is defined multiple times in the 'apply' patterns");
1431
};
1432
1433
for (auto &Pat : values(MatchPats)) {
1434
auto *IP = dyn_cast<InstructionPattern>(Pat.get());
1435
if (IP && !MatchOpTable.addPattern(IP, DiagnoseRedefMatch))
1436
return false;
1437
}
1438
1439
for (auto &Pat : values(ApplyPats)) {
1440
auto *IP = dyn_cast<InstructionPattern>(Pat.get());
1441
if (IP && !ApplyOpTable.addPattern(IP, DiagnoseRedefApply))
1442
return false;
1443
}
1444
1445
return true;
1446
}
1447
1448
bool CombineRuleBuilder::parseDefs(const DagInit &Def) {
1449
if (Def.getOperatorAsDef(RuleDef.getLoc())->getName() != "defs") {
1450
PrintError("Expected defs operator");
1451
return false;
1452
}
1453
1454
SmallVector<StringRef> Roots;
1455
for (unsigned I = 0, E = Def.getNumArgs(); I < E; ++I) {
1456
if (isSpecificDef(*Def.getArg(I), "root")) {
1457
Roots.emplace_back(Def.getArgNameStr(I));
1458
continue;
1459
}
1460
1461
// Subclasses of GIDefMatchData should declare that this rule needs to pass
1462
// data from the match stage to the apply stage, and ensure that the
1463
// generated matcher has a suitable variable for it to do so.
1464
if (Record *MatchDataRec =
1465
getDefOfSubClass(*Def.getArg(I), MatchDataClassName)) {
1466
MatchDatas.emplace_back(Def.getArgNameStr(I),
1467
MatchDataRec->getValueAsString("Type"));
1468
continue;
1469
}
1470
1471
// Otherwise emit an appropriate error message.
1472
if (getDefOfSubClass(*Def.getArg(I), "GIDefKind"))
1473
PrintError("This GIDefKind not implemented in tablegen");
1474
else if (getDefOfSubClass(*Def.getArg(I), "GIDefKindWithArgs"))
1475
PrintError("This GIDefKindWithArgs not implemented in tablegen");
1476
else
1477
PrintError("Expected a subclass of GIDefKind or a sub-dag whose "
1478
"operator is of type GIDefKindWithArgs");
1479
return false;
1480
}
1481
1482
if (Roots.size() != 1) {
1483
PrintError("Combine rules must have exactly one root");
1484
return false;
1485
}
1486
1487
RootName = Roots.front();
1488
return true;
1489
}
1490
1491
bool CombineRuleBuilder::emitMatchPattern(CodeExpansions &CE,
1492
const PatternAlternatives &Alts,
1493
const InstructionPattern &IP) {
1494
auto StackTrace = PrettyStackTraceEmit(RuleDef, &IP);
1495
1496
auto &M = addRuleMatcher(Alts);
1497
InstructionMatcher &IM = M.addInstructionMatcher(IP.getName());
1498
declareInstExpansion(CE, IM, IP.getName());
1499
1500
DenseSet<const Pattern *> SeenPats;
1501
1502
const auto FindOperandDef = [&](StringRef Op) -> InstructionPattern * {
1503
return MatchOpTable.getDef(Op);
1504
};
1505
1506
if (const auto *CGP = dyn_cast<CodeGenInstructionPattern>(&IP)) {
1507
if (!emitCodeGenInstructionMatchPattern(CE, Alts, M, IM, *CGP, SeenPats,
1508
FindOperandDef))
1509
return false;
1510
} else if (const auto *PFP = dyn_cast<PatFragPattern>(&IP)) {
1511
if (!PFP->getPatFrag().canBeMatchRoot()) {
1512
PrintError("cannot use '" + PFP->getInstName() + " as match root");
1513
return false;
1514
}
1515
1516
if (!emitPatFragMatchPattern(CE, Alts, M, &IM, *PFP, SeenPats))
1517
return false;
1518
} else if (isa<BuiltinPattern>(&IP)) {
1519
llvm_unreachable("No match builtins known!");
1520
} else
1521
llvm_unreachable("Unknown kind of InstructionPattern!");
1522
1523
// Emit remaining patterns
1524
const bool IsUsingCustomCXXAction = hasOnlyCXXApplyPatterns();
1525
SmallVector<CXXPattern *, 2> CXXMatchers;
1526
for (auto &Pat : values(MatchPats)) {
1527
if (SeenPats.contains(Pat.get()))
1528
continue;
1529
1530
switch (Pat->getKind()) {
1531
case Pattern::K_AnyOpcode:
1532
PrintError("wip_match_opcode can not be used with instruction patterns!");
1533
return false;
1534
case Pattern::K_PatFrag: {
1535
if (!emitPatFragMatchPattern(CE, Alts, M, /*IM*/ nullptr,
1536
*cast<PatFragPattern>(Pat.get()), SeenPats))
1537
return false;
1538
continue;
1539
}
1540
case Pattern::K_Builtin:
1541
PrintError("No known match builtins");
1542
return false;
1543
case Pattern::K_CodeGenInstruction:
1544
cast<InstructionPattern>(Pat.get())->reportUnreachable(RuleDef.getLoc());
1545
return false;
1546
case Pattern::K_CXX: {
1547
// Delay emission for top-level C++ matchers (which can use MatchDatas).
1548
if (IsUsingCustomCXXAction)
1549
CXXMatchers.push_back(cast<CXXPattern>(Pat.get()));
1550
else
1551
addCXXPredicate(M, CE, *cast<CXXPattern>(Pat.get()), Alts);
1552
continue;
1553
}
1554
default:
1555
llvm_unreachable("unknown pattern kind!");
1556
}
1557
}
1558
1559
return IsUsingCustomCXXAction ? emitCXXMatchApply(CE, M, CXXMatchers)
1560
: emitApplyPatterns(CE, M);
1561
}
1562
1563
bool CombineRuleBuilder::emitMatchPattern(CodeExpansions &CE,
1564
const PatternAlternatives &Alts,
1565
const AnyOpcodePattern &AOP) {
1566
auto StackTrace = PrettyStackTraceEmit(RuleDef, &AOP);
1567
1568
const bool IsUsingCustomCXXAction = hasOnlyCXXApplyPatterns();
1569
for (const CodeGenInstruction *CGI : AOP.insts()) {
1570
auto &M = addRuleMatcher(Alts, "wip_match_opcode '" +
1571
CGI->TheDef->getName() + "'");
1572
1573
InstructionMatcher &IM = M.addInstructionMatcher(AOP.getName());
1574
declareInstExpansion(CE, IM, AOP.getName());
1575
// declareInstExpansion needs to be identical, otherwise we need to create a
1576
// CodeExpansions object here instead.
1577
assert(IM.getInsnVarID() == 0);
1578
1579
IM.addPredicate<InstructionOpcodeMatcher>(CGI);
1580
1581
// Emit remaining patterns.
1582
SmallVector<CXXPattern *, 2> CXXMatchers;
1583
for (auto &Pat : values(MatchPats)) {
1584
if (Pat.get() == &AOP)
1585
continue;
1586
1587
switch (Pat->getKind()) {
1588
case Pattern::K_AnyOpcode:
1589
PrintError("wip_match_opcode can only be present once!");
1590
return false;
1591
case Pattern::K_PatFrag: {
1592
DenseSet<const Pattern *> SeenPats;
1593
if (!emitPatFragMatchPattern(CE, Alts, M, /*IM*/ nullptr,
1594
*cast<PatFragPattern>(Pat.get()),
1595
SeenPats))
1596
return false;
1597
continue;
1598
}
1599
case Pattern::K_Builtin:
1600
PrintError("No known match builtins");
1601
return false;
1602
case Pattern::K_CodeGenInstruction:
1603
cast<InstructionPattern>(Pat.get())->reportUnreachable(
1604
RuleDef.getLoc());
1605
return false;
1606
case Pattern::K_CXX: {
1607
// Delay emission for top-level C++ matchers (which can use MatchDatas).
1608
if (IsUsingCustomCXXAction)
1609
CXXMatchers.push_back(cast<CXXPattern>(Pat.get()));
1610
else
1611
addCXXPredicate(M, CE, *cast<CXXPattern>(Pat.get()), Alts);
1612
break;
1613
}
1614
default:
1615
llvm_unreachable("unknown pattern kind!");
1616
}
1617
}
1618
1619
const bool Res = IsUsingCustomCXXAction
1620
? emitCXXMatchApply(CE, M, CXXMatchers)
1621
: emitApplyPatterns(CE, M);
1622
if (!Res)
1623
return false;
1624
}
1625
1626
return true;
1627
}
1628
1629
bool CombineRuleBuilder::emitPatFragMatchPattern(
1630
CodeExpansions &CE, const PatternAlternatives &Alts, RuleMatcher &RM,
1631
InstructionMatcher *IM, const PatFragPattern &PFP,
1632
DenseSet<const Pattern *> &SeenPats) {
1633
auto StackTrace = PrettyStackTraceEmit(RuleDef, &PFP);
1634
1635
if (SeenPats.contains(&PFP))
1636
return true;
1637
SeenPats.insert(&PFP);
1638
1639
const auto &PF = PFP.getPatFrag();
1640
1641
if (!IM) {
1642
// When we don't have an IM, this means this PatFrag isn't reachable from
1643
// the root. This is only acceptable if it doesn't define anything (e.g. a
1644
// pure C++ PatFrag).
1645
if (PF.num_out_params() != 0) {
1646
PFP.reportUnreachable(RuleDef.getLoc());
1647
return false;
1648
}
1649
} else {
1650
// When an IM is provided, this is reachable from the root, and we're
1651
// expecting to have output operands.
1652
// TODO: If we want to allow for multiple roots we'll need a map of IMs
1653
// then, and emission becomes a bit more complicated.
1654
assert(PF.num_roots() == 1);
1655
}
1656
1657
CodeExpansions PatFragCEs;
1658
if (!PFP.mapInputCodeExpansions(CE, PatFragCEs, RuleDef.getLoc()))
1659
return false;
1660
1661
// List of {ParamName, ArgName}.
1662
// When all patterns have been emitted, find expansions in PatFragCEs named
1663
// ArgName and add their expansion to CE using ParamName as the key.
1664
SmallVector<std::pair<std::string, std::string>, 4> CEsToImport;
1665
1666
// Map parameter names to the actual argument.
1667
const auto OperandMapper =
1668
[&](const InstructionOperand &O) -> InstructionOperand {
1669
if (!O.isNamedOperand())
1670
return O;
1671
1672
StringRef ParamName = O.getOperandName();
1673
1674
// Not sure what to do with those tbh. They should probably never be here.
1675
assert(!O.isNamedImmediate() && "TODO: handle named imms");
1676
unsigned PIdx = PF.getParamIdx(ParamName);
1677
1678
// Map parameters to the argument values.
1679
if (PIdx == (unsigned)-1) {
1680
// This is a temp of the PatFragPattern, prefix the name to avoid
1681
// conflicts.
1682
return O.withNewName(
1683
insertStrRef((PFP.getName() + "." + ParamName).str()));
1684
}
1685
1686
// The operand will be added to PatFragCEs's code expansions using the
1687
// parameter's name. If it's bound to some operand during emission of the
1688
// patterns, we'll want to add it to CE.
1689
auto ArgOp = PFP.getOperand(PIdx);
1690
if (ArgOp.isNamedOperand())
1691
CEsToImport.emplace_back(ArgOp.getOperandName().str(), ParamName);
1692
1693
if (ArgOp.getType() && O.getType() && ArgOp.getType() != O.getType()) {
1694
StringRef PFName = PF.getName();
1695
PrintWarning("impossible type constraints: operand " + Twine(PIdx) +
1696
" of '" + PFP.getName() + "' has type '" +
1697
ArgOp.getType().str() + "', but '" + PFName +
1698
"' constrains it to '" + O.getType().str() + "'");
1699
if (ArgOp.isNamedOperand())
1700
PrintNote("operand " + Twine(PIdx) + " of '" + PFP.getName() +
1701
"' is '" + ArgOp.getOperandName() + "'");
1702
if (O.isNamedOperand())
1703
PrintNote("argument " + Twine(PIdx) + " of '" + PFName + "' is '" +
1704
ParamName + "'");
1705
}
1706
1707
return ArgOp;
1708
};
1709
1710
// PatFragPatterns are only made of InstructionPatterns or CXXPatterns.
1711
// Emit instructions from the root.
1712
const auto &FragAlt = PF.getAlternative(Alts.lookup(&PFP));
1713
const auto &FragAltOT = FragAlt.OpTable;
1714
const auto LookupOperandDef =
1715
[&](StringRef Op) -> const InstructionPattern * {
1716
return FragAltOT.getDef(Op);
1717
};
1718
1719
DenseSet<const Pattern *> PatFragSeenPats;
1720
for (const auto &[Idx, InOp] : enumerate(PF.out_params())) {
1721
if (InOp.Kind != PatFrag::PK_Root)
1722
continue;
1723
1724
StringRef ParamName = InOp.Name;
1725
const auto *Def = FragAltOT.getDef(ParamName);
1726
assert(Def && "PatFrag::checkSemantics should have emitted an error if "
1727
"an out operand isn't defined!");
1728
assert(isa<CodeGenInstructionPattern>(Def) &&
1729
"Nested PatFrags not supported yet");
1730
1731
if (!emitCodeGenInstructionMatchPattern(
1732
PatFragCEs, Alts, RM, *IM, *cast<CodeGenInstructionPattern>(Def),
1733
PatFragSeenPats, LookupOperandDef, OperandMapper))
1734
return false;
1735
}
1736
1737
// Emit leftovers.
1738
for (const auto &Pat : FragAlt.Pats) {
1739
if (PatFragSeenPats.contains(Pat.get()))
1740
continue;
1741
1742
if (const auto *CXXPat = dyn_cast<CXXPattern>(Pat.get())) {
1743
addCXXPredicate(RM, PatFragCEs, *CXXPat, Alts);
1744
continue;
1745
}
1746
1747
if (const auto *IP = dyn_cast<InstructionPattern>(Pat.get())) {
1748
IP->reportUnreachable(PF.getLoc());
1749
return false;
1750
}
1751
1752
llvm_unreachable("Unexpected pattern kind in PatFrag");
1753
}
1754
1755
for (const auto &[ParamName, ArgName] : CEsToImport) {
1756
// Note: we're find if ParamName already exists. It just means it's been
1757
// bound before, so we prefer to keep the first binding.
1758
CE.declare(ParamName, PatFragCEs.lookup(ArgName));
1759
}
1760
1761
return true;
1762
}
1763
1764
bool CombineRuleBuilder::emitApplyPatterns(CodeExpansions &CE, RuleMatcher &M) {
1765
assert(MatchDatas.empty());
1766
1767
DenseSet<const Pattern *> SeenPats;
1768
StringMap<unsigned> OperandToTempRegID;
1769
1770
for (auto *ApplyRoot : ApplyRoots) {
1771
assert(isa<InstructionPattern>(ApplyRoot) &&
1772
"Root can only be a InstructionPattern!");
1773
if (!emitInstructionApplyPattern(CE, M,
1774
cast<InstructionPattern>(*ApplyRoot),
1775
SeenPats, OperandToTempRegID))
1776
return false;
1777
}
1778
1779
for (auto &Pat : values(ApplyPats)) {
1780
if (SeenPats.contains(Pat.get()))
1781
continue;
1782
1783
switch (Pat->getKind()) {
1784
case Pattern::K_AnyOpcode:
1785
llvm_unreachable("Unexpected pattern in apply!");
1786
case Pattern::K_PatFrag:
1787
// TODO: We could support pure C++ PatFrags as a temporary thing.
1788
llvm_unreachable("Unexpected pattern in apply!");
1789
case Pattern::K_Builtin:
1790
if (!emitInstructionApplyPattern(CE, M, cast<BuiltinPattern>(*Pat),
1791
SeenPats, OperandToTempRegID))
1792
return false;
1793
break;
1794
case Pattern::K_CodeGenInstruction:
1795
cast<CodeGenInstructionPattern>(*Pat).reportUnreachable(RuleDef.getLoc());
1796
return false;
1797
case Pattern::K_CXX: {
1798
llvm_unreachable(
1799
"CXX Pattern Emission should have been handled earlier!");
1800
}
1801
default:
1802
llvm_unreachable("unknown pattern kind!");
1803
}
1804
}
1805
1806
// Erase the root.
1807
unsigned RootInsnID =
1808
M.getInsnVarID(M.getInstructionMatcher(MatchRoot->getName()));
1809
M.addAction<EraseInstAction>(RootInsnID);
1810
1811
return true;
1812
}
1813
1814
bool CombineRuleBuilder::emitCXXMatchApply(CodeExpansions &CE, RuleMatcher &M,
1815
ArrayRef<CXXPattern *> Matchers) {
1816
assert(hasOnlyCXXApplyPatterns());
1817
declareAllMatchDatasExpansions(CE);
1818
1819
std::string CodeStr;
1820
raw_string_ostream OS(CodeStr);
1821
1822
for (auto &MD : MatchDatas)
1823
OS << MD.Type << " " << MD.getVarName() << ";\n";
1824
1825
if (!Matchers.empty()) {
1826
OS << "// Match Patterns\n";
1827
for (auto *M : Matchers) {
1828
OS << "if(![&](){";
1829
CodeExpander Expander(M->getRawCode(), CE, RuleDef.getLoc(),
1830
/*ShowExpansions=*/false);
1831
Expander.emit(OS);
1832
OS << "}()) {\n"
1833
<< " return false;\n}\n";
1834
}
1835
}
1836
1837
OS << "// Apply Patterns\n";
1838
ListSeparator LS("\n");
1839
for (auto &Pat : ApplyPats) {
1840
auto *CXXPat = cast<CXXPattern>(Pat.second.get());
1841
CodeExpander Expander(CXXPat->getRawCode(), CE, RuleDef.getLoc(),
1842
/*ShowExpansions=*/ false);
1843
OS << LS;
1844
Expander.emit(OS);
1845
}
1846
1847
const auto &Code = CXXPredicateCode::getCustomActionCode(CodeStr);
1848
M.setCustomCXXAction(Code.getEnumNameWithPrefix(CXXCustomActionPrefix));
1849
return true;
1850
}
1851
1852
bool CombineRuleBuilder::emitInstructionApplyPattern(
1853
CodeExpansions &CE, RuleMatcher &M, const InstructionPattern &P,
1854
DenseSet<const Pattern *> &SeenPats,
1855
StringMap<unsigned> &OperandToTempRegID) {
1856
auto StackTrace = PrettyStackTraceEmit(RuleDef, &P);
1857
1858
if (SeenPats.contains(&P))
1859
return true;
1860
1861
SeenPats.insert(&P);
1862
1863
// First, render the uses.
1864
for (auto &Op : P.named_operands()) {
1865
if (Op.isDef())
1866
continue;
1867
1868
StringRef OpName = Op.getOperandName();
1869
if (const auto *DefPat = ApplyOpTable.getDef(OpName)) {
1870
if (!emitInstructionApplyPattern(CE, M, *DefPat, SeenPats,
1871
OperandToTempRegID))
1872
return false;
1873
} else {
1874
// If we have no def, check this exists in the MatchRoot.
1875
if (!Op.isNamedImmediate() && !MatchOpTable.lookup(OpName).Found) {
1876
PrintError("invalid output operand '" + OpName +
1877
"': operand is not a live-in of the match pattern, and it "
1878
"has no definition");
1879
return false;
1880
}
1881
}
1882
}
1883
1884
if (const auto *BP = dyn_cast<BuiltinPattern>(&P))
1885
return emitBuiltinApplyPattern(CE, M, *BP, OperandToTempRegID);
1886
1887
if (isa<PatFragPattern>(&P))
1888
llvm_unreachable("PatFragPatterns is not supported in 'apply'!");
1889
1890
auto &CGIP = cast<CodeGenInstructionPattern>(P);
1891
1892
// Now render this inst.
1893
auto &DstMI =
1894
M.addAction<BuildMIAction>(M.allocateOutputInsnID(), &CGIP.getInst());
1895
1896
bool HasEmittedIntrinsicID = false;
1897
const auto EmitIntrinsicID = [&]() {
1898
assert(CGIP.isIntrinsic());
1899
DstMI.addRenderer<IntrinsicIDRenderer>(CGIP.getIntrinsic());
1900
HasEmittedIntrinsicID = true;
1901
};
1902
1903
for (auto &Op : P.operands()) {
1904
// Emit the intrinsic ID after the last def.
1905
if (CGIP.isIntrinsic() && !Op.isDef() && !HasEmittedIntrinsicID)
1906
EmitIntrinsicID();
1907
1908
if (Op.isNamedImmediate()) {
1909
PrintError("invalid output operand '" + Op.getOperandName() +
1910
"': output immediates cannot be named");
1911
PrintNote("while emitting pattern '" + P.getName() + "' (" +
1912
P.getInstName() + ")");
1913
return false;
1914
}
1915
1916
if (Op.hasImmValue()) {
1917
if (!emitCodeGenInstructionApplyImmOperand(M, DstMI, CGIP, Op))
1918
return false;
1919
continue;
1920
}
1921
1922
StringRef OpName = Op.getOperandName();
1923
1924
// Uses of operand.
1925
if (!Op.isDef()) {
1926
if (auto It = OperandToTempRegID.find(OpName);
1927
It != OperandToTempRegID.end()) {
1928
assert(!MatchOpTable.lookup(OpName).Found &&
1929
"Temp reg is also from match pattern?");
1930
DstMI.addRenderer<TempRegRenderer>(It->second);
1931
} else {
1932
// This should be a match live in or a redef of a matched instr.
1933
// If it's a use of a temporary register, then we messed up somewhere -
1934
// the previous condition should have passed.
1935
assert(MatchOpTable.lookup(OpName).Found &&
1936
!ApplyOpTable.getDef(OpName) && "Temp reg not emitted yet!");
1937
DstMI.addRenderer<CopyRenderer>(OpName);
1938
}
1939
continue;
1940
}
1941
1942
// Determine what we're dealing with. Are we replace a matched instruction?
1943
// Creating a new one?
1944
auto OpLookupRes = MatchOpTable.lookup(OpName);
1945
if (OpLookupRes.Found) {
1946
if (OpLookupRes.isLiveIn()) {
1947
// live-in of the match pattern.
1948
PrintError("Cannot define live-in operand '" + OpName +
1949
"' in the 'apply' pattern");
1950
return false;
1951
}
1952
assert(OpLookupRes.Def);
1953
1954
// TODO: Handle this. We need to mutate the instr, or delete the old
1955
// one.
1956
// Likewise, we also need to ensure we redef everything, if the
1957
// instr has more than one def, we need to redef all or nothing.
1958
if (OpLookupRes.Def != MatchRoot) {
1959
PrintError("redefining an instruction other than the root is not "
1960
"supported (operand '" +
1961
OpName + "')");
1962
return false;
1963
}
1964
// redef of a match
1965
DstMI.addRenderer<CopyRenderer>(OpName);
1966
continue;
1967
}
1968
1969
// Define a new register unique to the apply patterns (AKA a "temp"
1970
// register).
1971
unsigned TempRegID;
1972
if (auto It = OperandToTempRegID.find(OpName);
1973
It != OperandToTempRegID.end()) {
1974
TempRegID = It->second;
1975
} else {
1976
// This is a brand new register.
1977
TempRegID = M.allocateTempRegID();
1978
OperandToTempRegID[OpName] = TempRegID;
1979
const auto Ty = Op.getType();
1980
if (!Ty) {
1981
PrintError("def of a new register '" + OpName +
1982
"' in the apply patterns must have a type");
1983
return false;
1984
}
1985
1986
declareTempRegExpansion(CE, TempRegID, OpName);
1987
// Always insert the action at the beginning, otherwise we may end up
1988
// using the temp reg before it's available.
1989
M.insertAction<MakeTempRegisterAction>(
1990
M.actions_begin(), getLLTCodeGenOrTempType(Ty, M), TempRegID);
1991
}
1992
1993
DstMI.addRenderer<TempRegRenderer>(TempRegID, /*IsDef=*/true);
1994
}
1995
1996
// Some intrinsics have no in operands, ensure the ID is still emitted in such
1997
// cases.
1998
if (CGIP.isIntrinsic() && !HasEmittedIntrinsicID)
1999
EmitIntrinsicID();
2000
2001
// Render MIFlags
2002
if (const auto *FI = CGIP.getMIFlagsInfo()) {
2003
for (StringRef InstName : FI->copy_flags())
2004
DstMI.addCopiedMIFlags(M.getInstructionMatcher(InstName));
2005
for (StringRef F : FI->set_flags())
2006
DstMI.addSetMIFlags(F);
2007
for (StringRef F : FI->unset_flags())
2008
DstMI.addUnsetMIFlags(F);
2009
}
2010
2011
// Don't allow mutating opcodes for GISel combiners. We want a more precise
2012
// handling of MIFlags so we require them to be explicitly preserved.
2013
//
2014
// TODO: We don't mutate very often, if at all in combiners, but it'd be nice
2015
// to re-enable this. We'd then need to always clear MIFlags when mutating
2016
// opcodes, and never mutate an inst that we copy flags from.
2017
// DstMI.chooseInsnToMutate(M);
2018
declareInstExpansion(CE, DstMI, P.getName());
2019
2020
return true;
2021
}
2022
2023
bool CombineRuleBuilder::emitCodeGenInstructionApplyImmOperand(
2024
RuleMatcher &M, BuildMIAction &DstMI, const CodeGenInstructionPattern &P,
2025
const InstructionOperand &O) {
2026
// If we have a type, we implicitly emit a G_CONSTANT, except for G_CONSTANT
2027
// itself where we emit a CImm.
2028
//
2029
// No type means we emit a simple imm.
2030
// G_CONSTANT is a special case and needs a CImm though so this is likely a
2031
// mistake.
2032
const bool isGConstant = P.is("G_CONSTANT");
2033
const auto Ty = O.getType();
2034
if (!Ty) {
2035
if (isGConstant) {
2036
PrintError("'G_CONSTANT' immediate must be typed!");
2037
PrintNote("while emitting pattern '" + P.getName() + "' (" +
2038
P.getInstName() + ")");
2039
return false;
2040
}
2041
2042
DstMI.addRenderer<ImmRenderer>(O.getImmValue());
2043
return true;
2044
}
2045
2046
auto ImmTy = getLLTCodeGenOrTempType(Ty, M);
2047
2048
if (isGConstant) {
2049
DstMI.addRenderer<ImmRenderer>(O.getImmValue(), ImmTy);
2050
return true;
2051
}
2052
2053
unsigned TempRegID = M.allocateTempRegID();
2054
// Ensure MakeTempReg & the BuildConstantAction occur at the beginning.
2055
auto InsertIt = M.insertAction<MakeTempRegisterAction>(M.actions_begin(),
2056
ImmTy, TempRegID);
2057
M.insertAction<BuildConstantAction>(++InsertIt, TempRegID, O.getImmValue());
2058
DstMI.addRenderer<TempRegRenderer>(TempRegID);
2059
return true;
2060
}
2061
2062
bool CombineRuleBuilder::emitBuiltinApplyPattern(
2063
CodeExpansions &CE, RuleMatcher &M, const BuiltinPattern &P,
2064
StringMap<unsigned> &OperandToTempRegID) {
2065
const auto Error = [&](Twine Reason) {
2066
PrintError("cannot emit '" + P.getInstName() + "' builtin: " + Reason);
2067
return false;
2068
};
2069
2070
switch (P.getBuiltinKind()) {
2071
case BI_EraseRoot: {
2072
// Root is always inst 0.
2073
M.addAction<EraseInstAction>(/*InsnID*/ 0);
2074
return true;
2075
}
2076
case BI_ReplaceReg: {
2077
StringRef Old = P.getOperand(0).getOperandName();
2078
StringRef New = P.getOperand(1).getOperandName();
2079
2080
if (!ApplyOpTable.lookup(New).Found && !MatchOpTable.lookup(New).Found)
2081
return Error("unknown operand '" + Old + "'");
2082
2083
auto &OldOM = M.getOperandMatcher(Old);
2084
if (auto It = OperandToTempRegID.find(New);
2085
It != OperandToTempRegID.end()) {
2086
// Replace with temp reg.
2087
M.addAction<ReplaceRegAction>(OldOM.getInsnVarID(), OldOM.getOpIdx(),
2088
It->second);
2089
} else {
2090
// Replace with matched reg.
2091
auto &NewOM = M.getOperandMatcher(New);
2092
M.addAction<ReplaceRegAction>(OldOM.getInsnVarID(), OldOM.getOpIdx(),
2093
NewOM.getInsnVarID(), NewOM.getOpIdx());
2094
}
2095
// checkSemantics should have ensured that we can only rewrite the root.
2096
// Ensure we're deleting it.
2097
assert(MatchOpTable.getDef(Old) == MatchRoot);
2098
return true;
2099
}
2100
}
2101
2102
llvm_unreachable("Unknown BuiltinKind!");
2103
}
2104
2105
bool isLiteralImm(const InstructionPattern &P, unsigned OpIdx) {
2106
if (const auto *CGP = dyn_cast<CodeGenInstructionPattern>(&P)) {
2107
StringRef InstName = CGP->getInst().TheDef->getName();
2108
return (InstName == "G_CONSTANT" || InstName == "G_FCONSTANT") &&
2109
OpIdx == 1;
2110
}
2111
2112
llvm_unreachable("TODO");
2113
}
2114
2115
bool CombineRuleBuilder::emitCodeGenInstructionMatchPattern(
2116
CodeExpansions &CE, const PatternAlternatives &Alts, RuleMatcher &M,
2117
InstructionMatcher &IM, const CodeGenInstructionPattern &P,
2118
DenseSet<const Pattern *> &SeenPats, OperandDefLookupFn LookupOperandDef,
2119
OperandMapperFnRef OperandMapper) {
2120
auto StackTrace = PrettyStackTraceEmit(RuleDef, &P);
2121
2122
if (SeenPats.contains(&P))
2123
return true;
2124
2125
SeenPats.insert(&P);
2126
2127
IM.addPredicate<InstructionOpcodeMatcher>(&P.getInst());
2128
declareInstExpansion(CE, IM, P.getName());
2129
2130
// If this is an intrinsic, check the intrinsic ID.
2131
if (P.isIntrinsic()) {
2132
// The IntrinsicID's operand is the first operand after the defs.
2133
OperandMatcher &OM = IM.addOperand(P.getNumInstDefs(), "$intrinsic_id",
2134
AllocatedTemporariesBaseID++);
2135
OM.addPredicate<IntrinsicIDOperandMatcher>(P.getIntrinsic());
2136
}
2137
2138
// Check flags if needed.
2139
if (const auto *FI = P.getMIFlagsInfo()) {
2140
assert(FI->copy_flags().empty());
2141
2142
if (const auto &SetF = FI->set_flags(); !SetF.empty())
2143
IM.addPredicate<MIFlagsInstructionPredicateMatcher>(SetF.getArrayRef());
2144
if (const auto &UnsetF = FI->unset_flags(); !UnsetF.empty())
2145
IM.addPredicate<MIFlagsInstructionPredicateMatcher>(UnsetF.getArrayRef(),
2146
/*CheckNot=*/true);
2147
}
2148
2149
for (auto [Idx, OriginalO] : enumerate(P.operands())) {
2150
// Remap the operand. This is used when emitting InstructionPatterns inside
2151
// PatFrags, so it can remap them to the arguments passed to the pattern.
2152
//
2153
// We use the remapped operand to emit immediates, and for the symbolic
2154
// operand names (in IM.addOperand). CodeExpansions and OperandTable lookups
2155
// still use the original name.
2156
//
2157
// The "def" flag on the remapped operand is always ignored.
2158
auto RemappedO = OperandMapper(OriginalO);
2159
assert(RemappedO.isNamedOperand() == OriginalO.isNamedOperand() &&
2160
"Cannot remap an unnamed operand to a named one!");
2161
2162
const auto OpName =
2163
RemappedO.isNamedOperand() ? RemappedO.getOperandName().str() : "";
2164
2165
// For intrinsics, the first use operand is the intrinsic id, so the true
2166
// operand index is shifted by 1.
2167
//
2168
// From now on:
2169
// Idx = index in the pattern operand list.
2170
// RealIdx = expected index in the MachineInstr.
2171
const unsigned RealIdx =
2172
(P.isIntrinsic() && !OriginalO.isDef()) ? (Idx + 1) : Idx;
2173
OperandMatcher &OM =
2174
IM.addOperand(RealIdx, OpName, AllocatedTemporariesBaseID++);
2175
if (!OpName.empty())
2176
declareOperandExpansion(CE, OM, OriginalO.getOperandName());
2177
2178
// Handle immediates.
2179
if (RemappedO.hasImmValue()) {
2180
if (isLiteralImm(P, Idx))
2181
OM.addPredicate<LiteralIntOperandMatcher>(RemappedO.getImmValue());
2182
else
2183
OM.addPredicate<ConstantIntOperandMatcher>(RemappedO.getImmValue());
2184
}
2185
2186
// Handle typed operands, but only bother to check if it hasn't been done
2187
// before.
2188
//
2189
// getOperandMatcher will always return the first OM to have been created
2190
// for that Operand. "OM" here is always a new OperandMatcher.
2191
//
2192
// Always emit a check for unnamed operands.
2193
if (OpName.empty() ||
2194
!M.getOperandMatcher(OpName).contains<LLTOperandMatcher>()) {
2195
if (const auto Ty = RemappedO.getType()) {
2196
// TODO: We could support GITypeOf here on the condition that the
2197
// OperandMatcher exists already. Though it's clunky to make this work
2198
// and isn't all that useful so it's just rejected in typecheckPatterns
2199
// at this time.
2200
assert(Ty.isLLT() && "Only LLTs are supported in match patterns!");
2201
OM.addPredicate<LLTOperandMatcher>(getLLTCodeGen(Ty));
2202
}
2203
}
2204
2205
// Stop here if the operand is a def, or if it had no name.
2206
if (OriginalO.isDef() || !OriginalO.isNamedOperand())
2207
continue;
2208
2209
const auto *DefPat = LookupOperandDef(OriginalO.getOperandName());
2210
if (!DefPat)
2211
continue;
2212
2213
if (OriginalO.hasImmValue()) {
2214
assert(!OpName.empty());
2215
// This is a named immediate that also has a def, that's not okay.
2216
// e.g.
2217
// (G_SEXT $y, (i32 0))
2218
// (COPY $x, 42:$y)
2219
PrintError("'" + OpName +
2220
"' is a named immediate, it cannot be defined by another "
2221
"instruction");
2222
PrintNote("'" + OpName + "' is defined by '" + DefPat->getName() + "'");
2223
return false;
2224
}
2225
2226
// From here we know that the operand defines an instruction, and we need to
2227
// emit it.
2228
auto InstOpM =
2229
OM.addPredicate<InstructionOperandMatcher>(M, DefPat->getName());
2230
if (!InstOpM) {
2231
// TODO: copy-pasted from GlobalISelEmitter.cpp. Is it still relevant
2232
// here?
2233
PrintError("Nested instruction '" + DefPat->getName() +
2234
"' cannot be the same as another operand '" +
2235
OriginalO.getOperandName() + "'");
2236
return false;
2237
}
2238
2239
auto &IM = (*InstOpM)->getInsnMatcher();
2240
if (const auto *CGIDef = dyn_cast<CodeGenInstructionPattern>(DefPat)) {
2241
if (!emitCodeGenInstructionMatchPattern(CE, Alts, M, IM, *CGIDef,
2242
SeenPats, LookupOperandDef,
2243
OperandMapper))
2244
return false;
2245
continue;
2246
}
2247
2248
if (const auto *PFPDef = dyn_cast<PatFragPattern>(DefPat)) {
2249
if (!emitPatFragMatchPattern(CE, Alts, M, &IM, *PFPDef, SeenPats))
2250
return false;
2251
continue;
2252
}
2253
2254
llvm_unreachable("unknown type of InstructionPattern");
2255
}
2256
2257
return true;
2258
}
2259
2260
//===- GICombinerEmitter --------------------------------------------------===//
2261
2262
/// Main implementation class. This emits the tablegenerated output.
2263
///
2264
/// It collects rules, uses `CombineRuleBuilder` to parse them and accumulate
2265
/// RuleMatchers, then takes all the necessary state/data from the various
2266
/// static storage pools and wires them together to emit the match table &
2267
/// associated function/data structures.
2268
class GICombinerEmitter final : public GlobalISelMatchTableExecutorEmitter {
2269
RecordKeeper &Records;
2270
StringRef Name;
2271
const CodeGenTarget &Target;
2272
Record *Combiner;
2273
unsigned NextRuleID = 0;
2274
2275
// List all combine rules (ID, name) imported.
2276
// Note that the combiner rule ID is different from the RuleMatcher ID. The
2277
// latter is internal to the MatchTable, the former is the canonical ID of the
2278
// combine rule used to disable/enable it.
2279
std::vector<std::pair<unsigned, std::string>> AllCombineRules;
2280
2281
// Keep track of all rules we've seen so far to ensure we don't process
2282
// the same rule twice.
2283
StringSet<> RulesSeen;
2284
2285
MatchTable buildMatchTable(MutableArrayRef<RuleMatcher> Rules);
2286
2287
void emitRuleConfigImpl(raw_ostream &OS);
2288
2289
void emitAdditionalImpl(raw_ostream &OS) override;
2290
2291
void emitMIPredicateFns(raw_ostream &OS) override;
2292
void emitI64ImmPredicateFns(raw_ostream &OS) override;
2293
void emitAPFloatImmPredicateFns(raw_ostream &OS) override;
2294
void emitAPIntImmPredicateFns(raw_ostream &OS) override;
2295
void emitTestSimplePredicate(raw_ostream &OS) override;
2296
void emitRunCustomAction(raw_ostream &OS) override;
2297
2298
const CodeGenTarget &getTarget() const override { return Target; }
2299
StringRef getClassName() const override {
2300
return Combiner->getValueAsString("Classname");
2301
}
2302
2303
StringRef getCombineAllMethodName() const {
2304
return Combiner->getValueAsString("CombineAllMethodName");
2305
}
2306
2307
std::string getRuleConfigClassName() const {
2308
return getClassName().str() + "RuleConfig";
2309
}
2310
2311
void gatherRules(std::vector<RuleMatcher> &Rules,
2312
const std::vector<Record *> &&RulesAndGroups);
2313
2314
public:
2315
explicit GICombinerEmitter(RecordKeeper &RK, const CodeGenTarget &Target,
2316
StringRef Name, Record *Combiner);
2317
~GICombinerEmitter() {}
2318
2319
void run(raw_ostream &OS);
2320
};
2321
2322
void GICombinerEmitter::emitRuleConfigImpl(raw_ostream &OS) {
2323
OS << "struct " << getRuleConfigClassName() << " {\n"
2324
<< " SparseBitVector<> DisabledRules;\n\n"
2325
<< " bool isRuleEnabled(unsigned RuleID) const;\n"
2326
<< " bool parseCommandLineOption();\n"
2327
<< " bool setRuleEnabled(StringRef RuleIdentifier);\n"
2328
<< " bool setRuleDisabled(StringRef RuleIdentifier);\n"
2329
<< "};\n\n";
2330
2331
std::vector<std::pair<std::string, std::string>> Cases;
2332
Cases.reserve(AllCombineRules.size());
2333
2334
for (const auto &[ID, Name] : AllCombineRules)
2335
Cases.emplace_back(Name, "return " + to_string(ID) + ";\n");
2336
2337
OS << "static std::optional<uint64_t> getRuleIdxForIdentifier(StringRef "
2338
"RuleIdentifier) {\n"
2339
<< " uint64_t I;\n"
2340
<< " // getAtInteger(...) returns false on success\n"
2341
<< " bool Parsed = !RuleIdentifier.getAsInteger(0, I);\n"
2342
<< " if (Parsed)\n"
2343
<< " return I;\n\n"
2344
<< "#ifndef NDEBUG\n";
2345
StringMatcher Matcher("RuleIdentifier", Cases, OS);
2346
Matcher.Emit();
2347
OS << "#endif // ifndef NDEBUG\n\n"
2348
<< " return std::nullopt;\n"
2349
<< "}\n";
2350
2351
OS << "static std::optional<std::pair<uint64_t, uint64_t>> "
2352
"getRuleRangeForIdentifier(StringRef RuleIdentifier) {\n"
2353
<< " std::pair<StringRef, StringRef> RangePair = "
2354
"RuleIdentifier.split('-');\n"
2355
<< " if (!RangePair.second.empty()) {\n"
2356
<< " const auto First = "
2357
"getRuleIdxForIdentifier(RangePair.first);\n"
2358
<< " const auto Last = "
2359
"getRuleIdxForIdentifier(RangePair.second);\n"
2360
<< " if (!First || !Last)\n"
2361
<< " return std::nullopt;\n"
2362
<< " if (First >= Last)\n"
2363
<< " report_fatal_error(\"Beginning of range should be before "
2364
"end of range\");\n"
2365
<< " return {{*First, *Last + 1}};\n"
2366
<< " }\n"
2367
<< " if (RangePair.first == \"*\") {\n"
2368
<< " return {{0, " << AllCombineRules.size() << "}};\n"
2369
<< " }\n"
2370
<< " const auto I = getRuleIdxForIdentifier(RangePair.first);\n"
2371
<< " if (!I)\n"
2372
<< " return std::nullopt;\n"
2373
<< " return {{*I, *I + 1}};\n"
2374
<< "}\n\n";
2375
2376
for (bool Enabled : {true, false}) {
2377
OS << "bool " << getRuleConfigClassName() << "::setRule"
2378
<< (Enabled ? "Enabled" : "Disabled") << "(StringRef RuleIdentifier) {\n"
2379
<< " auto MaybeRange = getRuleRangeForIdentifier(RuleIdentifier);\n"
2380
<< " if (!MaybeRange)\n"
2381
<< " return false;\n"
2382
<< " for (auto I = MaybeRange->first; I < MaybeRange->second; ++I)\n"
2383
<< " DisabledRules." << (Enabled ? "reset" : "set") << "(I);\n"
2384
<< " return true;\n"
2385
<< "}\n\n";
2386
}
2387
2388
OS << "static std::vector<std::string> " << Name << "Option;\n"
2389
<< "static cl::list<std::string> " << Name << "DisableOption(\n"
2390
<< " \"" << Name.lower() << "-disable-rule\",\n"
2391
<< " cl::desc(\"Disable one or more combiner rules temporarily in "
2392
<< "the " << Name << " pass\"),\n"
2393
<< " cl::CommaSeparated,\n"
2394
<< " cl::Hidden,\n"
2395
<< " cl::cat(GICombinerOptionCategory),\n"
2396
<< " cl::callback([](const std::string &Str) {\n"
2397
<< " " << Name << "Option.push_back(Str);\n"
2398
<< " }));\n"
2399
<< "static cl::list<std::string> " << Name << "OnlyEnableOption(\n"
2400
<< " \"" << Name.lower() << "-only-enable-rule\",\n"
2401
<< " cl::desc(\"Disable all rules in the " << Name
2402
<< " pass then re-enable the specified ones\"),\n"
2403
<< " cl::Hidden,\n"
2404
<< " cl::cat(GICombinerOptionCategory),\n"
2405
<< " cl::callback([](const std::string &CommaSeparatedArg) {\n"
2406
<< " StringRef Str = CommaSeparatedArg;\n"
2407
<< " " << Name << "Option.push_back(\"*\");\n"
2408
<< " do {\n"
2409
<< " auto X = Str.split(\",\");\n"
2410
<< " " << Name << "Option.push_back((\"!\" + X.first).str());\n"
2411
<< " Str = X.second;\n"
2412
<< " } while (!Str.empty());\n"
2413
<< " }));\n"
2414
<< "\n\n"
2415
<< "bool " << getRuleConfigClassName()
2416
<< "::isRuleEnabled(unsigned RuleID) const {\n"
2417
<< " return !DisabledRules.test(RuleID);\n"
2418
<< "}\n"
2419
<< "bool " << getRuleConfigClassName() << "::parseCommandLineOption() {\n"
2420
<< " for (StringRef Identifier : " << Name << "Option) {\n"
2421
<< " bool Enabled = Identifier.consume_front(\"!\");\n"
2422
<< " if (Enabled && !setRuleEnabled(Identifier))\n"
2423
<< " return false;\n"
2424
<< " if (!Enabled && !setRuleDisabled(Identifier))\n"
2425
<< " return false;\n"
2426
<< " }\n"
2427
<< " return true;\n"
2428
<< "}\n\n";
2429
}
2430
2431
void GICombinerEmitter::emitAdditionalImpl(raw_ostream &OS) {
2432
OS << "bool " << getClassName() << "::" << getCombineAllMethodName()
2433
<< "(MachineInstr &I) const {\n"
2434
<< " const TargetSubtargetInfo &ST = MF.getSubtarget();\n"
2435
<< " const PredicateBitset AvailableFeatures = "
2436
"getAvailableFeatures();\n"
2437
<< " B.setInstrAndDebugLoc(I);\n"
2438
<< " State.MIs.clear();\n"
2439
<< " State.MIs.push_back(&I);\n"
2440
<< " if (executeMatchTable(*this, State, ExecInfo, B"
2441
<< ", getMatchTable(), *ST.getInstrInfo(), MRI, "
2442
"*MRI.getTargetRegisterInfo(), *ST.getRegBankInfo(), AvailableFeatures"
2443
<< ", /*CoverageInfo*/ nullptr)) {\n"
2444
<< " return true;\n"
2445
<< " }\n\n"
2446
<< " return false;\n"
2447
<< "}\n\n";
2448
}
2449
2450
void GICombinerEmitter::emitMIPredicateFns(raw_ostream &OS) {
2451
auto MatchCode = CXXPredicateCode::getAllMatchCode();
2452
emitMIPredicateFnsImpl<const CXXPredicateCode *>(
2453
OS, "", ArrayRef<const CXXPredicateCode *>(MatchCode),
2454
[](const CXXPredicateCode *C) -> StringRef { return C->BaseEnumName; },
2455
[](const CXXPredicateCode *C) -> StringRef { return C->Code; });
2456
}
2457
2458
void GICombinerEmitter::emitI64ImmPredicateFns(raw_ostream &OS) {
2459
// Unused, but still needs to be called.
2460
emitImmPredicateFnsImpl<unsigned>(
2461
OS, "I64", "int64_t", {}, [](unsigned) { return ""; },
2462
[](unsigned) { return ""; });
2463
}
2464
2465
void GICombinerEmitter::emitAPFloatImmPredicateFns(raw_ostream &OS) {
2466
// Unused, but still needs to be called.
2467
emitImmPredicateFnsImpl<unsigned>(
2468
OS, "APFloat", "const APFloat &", {}, [](unsigned) { return ""; },
2469
[](unsigned) { return ""; });
2470
}
2471
2472
void GICombinerEmitter::emitAPIntImmPredicateFns(raw_ostream &OS) {
2473
// Unused, but still needs to be called.
2474
emitImmPredicateFnsImpl<unsigned>(
2475
OS, "APInt", "const APInt &", {}, [](unsigned) { return ""; },
2476
[](unsigned) { return ""; });
2477
}
2478
2479
void GICombinerEmitter::emitTestSimplePredicate(raw_ostream &OS) {
2480
if (!AllCombineRules.empty()) {
2481
OS << "enum {\n";
2482
std::string EnumeratorSeparator = " = GICXXPred_Invalid + 1,\n";
2483
// To avoid emitting a switch, we expect that all those rules are in order.
2484
// That way we can just get the RuleID from the enum by subtracting
2485
// (GICXXPred_Invalid + 1).
2486
unsigned ExpectedID = 0;
2487
(void)ExpectedID;
2488
for (const auto &ID : keys(AllCombineRules)) {
2489
assert(ExpectedID++ == ID && "combine rules are not ordered!");
2490
OS << " " << getIsEnabledPredicateEnumName(ID) << EnumeratorSeparator;
2491
EnumeratorSeparator = ",\n";
2492
}
2493
OS << "};\n\n";
2494
}
2495
2496
OS << "bool " << getClassName()
2497
<< "::testSimplePredicate(unsigned Predicate) const {\n"
2498
<< " return RuleConfig.isRuleEnabled(Predicate - "
2499
"GICXXPred_Invalid - "
2500
"1);\n"
2501
<< "}\n";
2502
}
2503
2504
void GICombinerEmitter::emitRunCustomAction(raw_ostream &OS) {
2505
const auto CustomActionsCode = CXXPredicateCode::getAllCustomActionsCode();
2506
2507
if (!CustomActionsCode.empty()) {
2508
OS << "enum {\n";
2509
std::string EnumeratorSeparator = " = GICXXCustomAction_Invalid + 1,\n";
2510
for (const auto &CA : CustomActionsCode) {
2511
OS << " " << CA->getEnumNameWithPrefix(CXXCustomActionPrefix)
2512
<< EnumeratorSeparator;
2513
EnumeratorSeparator = ",\n";
2514
}
2515
OS << "};\n";
2516
}
2517
2518
OS << "bool " << getClassName()
2519
<< "::runCustomAction(unsigned ApplyID, const MatcherState &State, "
2520
"NewMIVector &OutMIs) const "
2521
"{\n Helper.getBuilder().setInstrAndDebugLoc(*State.MIs[0]);\n";
2522
if (!CustomActionsCode.empty()) {
2523
OS << " switch(ApplyID) {\n";
2524
for (const auto &CA : CustomActionsCode) {
2525
OS << " case " << CA->getEnumNameWithPrefix(CXXCustomActionPrefix)
2526
<< ":{\n"
2527
<< " " << join(split(CA->Code, '\n'), "\n ") << '\n'
2528
<< " return true;\n";
2529
OS << " }\n";
2530
}
2531
OS << " }\n";
2532
}
2533
OS << " llvm_unreachable(\"Unknown Apply Action\");\n"
2534
<< "}\n";
2535
}
2536
2537
GICombinerEmitter::GICombinerEmitter(RecordKeeper &RK,
2538
const CodeGenTarget &Target,
2539
StringRef Name, Record *Combiner)
2540
: Records(RK), Name(Name), Target(Target), Combiner(Combiner) {}
2541
2542
MatchTable
2543
GICombinerEmitter::buildMatchTable(MutableArrayRef<RuleMatcher> Rules) {
2544
std::vector<Matcher *> InputRules;
2545
for (Matcher &Rule : Rules)
2546
InputRules.push_back(&Rule);
2547
2548
unsigned CurrentOrdering = 0;
2549
StringMap<unsigned> OpcodeOrder;
2550
for (RuleMatcher &Rule : Rules) {
2551
const StringRef Opcode = Rule.getOpcode();
2552
assert(!Opcode.empty() && "Didn't expect an undefined opcode");
2553
if (OpcodeOrder.count(Opcode) == 0)
2554
OpcodeOrder[Opcode] = CurrentOrdering++;
2555
}
2556
2557
llvm::stable_sort(InputRules, [&OpcodeOrder](const Matcher *A,
2558
const Matcher *B) {
2559
auto *L = static_cast<const RuleMatcher *>(A);
2560
auto *R = static_cast<const RuleMatcher *>(B);
2561
return std::make_tuple(OpcodeOrder[L->getOpcode()], L->getNumOperands()) <
2562
std::make_tuple(OpcodeOrder[R->getOpcode()], R->getNumOperands());
2563
});
2564
2565
for (Matcher *Rule : InputRules)
2566
Rule->optimize();
2567
2568
std::vector<std::unique_ptr<Matcher>> MatcherStorage;
2569
std::vector<Matcher *> OptRules =
2570
optimizeRules<GroupMatcher>(InputRules, MatcherStorage);
2571
2572
for (Matcher *Rule : OptRules)
2573
Rule->optimize();
2574
2575
OptRules = optimizeRules<SwitchMatcher>(OptRules, MatcherStorage);
2576
2577
return MatchTable::buildTable(OptRules, /*WithCoverage*/ false,
2578
/*IsCombiner*/ true);
2579
}
2580
2581
/// Recurse into GICombineGroup's and flatten the ruleset into a simple list.
2582
void GICombinerEmitter::gatherRules(
2583
std::vector<RuleMatcher> &ActiveRules,
2584
const std::vector<Record *> &&RulesAndGroups) {
2585
for (Record *Rec : RulesAndGroups) {
2586
if (!Rec->isValueUnset("Rules")) {
2587
gatherRules(ActiveRules, Rec->getValueAsListOfDefs("Rules"));
2588
continue;
2589
}
2590
2591
StringRef RuleName = Rec->getName();
2592
if (!RulesSeen.insert(RuleName).second) {
2593
PrintWarning(Rec->getLoc(),
2594
"skipping rule '" + Rec->getName() +
2595
"' because it has already been processed");
2596
continue;
2597
}
2598
2599
AllCombineRules.emplace_back(NextRuleID, Rec->getName().str());
2600
CombineRuleBuilder CRB(Target, SubtargetFeatures, *Rec, NextRuleID++,
2601
ActiveRules);
2602
2603
if (!CRB.parseAll()) {
2604
assert(ErrorsPrinted && "Parsing failed without errors!");
2605
continue;
2606
}
2607
2608
if (StopAfterParse) {
2609
CRB.print(outs());
2610
continue;
2611
}
2612
2613
if (!CRB.emitRuleMatchers()) {
2614
assert(ErrorsPrinted && "Emission failed without errors!");
2615
continue;
2616
}
2617
}
2618
}
2619
2620
void GICombinerEmitter::run(raw_ostream &OS) {
2621
InstructionOpcodeMatcher::initOpcodeValuesMap(Target);
2622
LLTOperandMatcher::initTypeIDValuesMap();
2623
2624
Records.startTimer("Gather rules");
2625
std::vector<RuleMatcher> Rules;
2626
gatherRules(Rules, Combiner->getValueAsListOfDefs("Rules"));
2627
if (ErrorsPrinted)
2628
PrintFatalError(Combiner->getLoc(), "Failed to parse one or more rules");
2629
2630
if (StopAfterParse)
2631
return;
2632
2633
Records.startTimer("Creating Match Table");
2634
unsigned MaxTemporaries = 0;
2635
for (const auto &Rule : Rules)
2636
MaxTemporaries = std::max(MaxTemporaries, Rule.countRendererFns());
2637
2638
llvm::stable_sort(Rules, [&](const RuleMatcher &A, const RuleMatcher &B) {
2639
if (A.isHigherPriorityThan(B)) {
2640
assert(!B.isHigherPriorityThan(A) && "Cannot be more important "
2641
"and less important at "
2642
"the same time");
2643
return true;
2644
}
2645
return false;
2646
});
2647
2648
const MatchTable Table = buildMatchTable(Rules);
2649
2650
Records.startTimer("Emit combiner");
2651
2652
emitSourceFileHeader(getClassName().str() + " Combiner Match Table", OS);
2653
2654
// Unused
2655
std::vector<StringRef> CustomRendererFns;
2656
// Unused
2657
std::vector<Record *> ComplexPredicates;
2658
2659
SmallVector<LLTCodeGen, 16> TypeObjects;
2660
append_range(TypeObjects, KnownTypes);
2661
llvm::sort(TypeObjects);
2662
2663
// Hack: Avoid empty declarator.
2664
if (TypeObjects.empty())
2665
TypeObjects.push_back(LLT::scalar(1));
2666
2667
// GET_GICOMBINER_DEPS, which pulls in extra dependencies.
2668
OS << "#ifdef GET_GICOMBINER_DEPS\n"
2669
<< "#include \"llvm/ADT/SparseBitVector.h\"\n"
2670
<< "namespace llvm {\n"
2671
<< "extern cl::OptionCategory GICombinerOptionCategory;\n"
2672
<< "} // end namespace llvm\n"
2673
<< "#endif // ifdef GET_GICOMBINER_DEPS\n\n";
2674
2675
// GET_GICOMBINER_TYPES, which needs to be included before the declaration of
2676
// the class.
2677
OS << "#ifdef GET_GICOMBINER_TYPES\n";
2678
emitRuleConfigImpl(OS);
2679
OS << "#endif // ifdef GET_GICOMBINER_TYPES\n\n";
2680
emitPredicateBitset(OS, "GET_GICOMBINER_TYPES");
2681
2682
// GET_GICOMBINER_CLASS_MEMBERS, which need to be included inside the class.
2683
emitPredicatesDecl(OS, "GET_GICOMBINER_CLASS_MEMBERS");
2684
emitTemporariesDecl(OS, "GET_GICOMBINER_CLASS_MEMBERS");
2685
2686
// GET_GICOMBINER_IMPL, which needs to be included outside the class.
2687
emitExecutorImpl(OS, Table, TypeObjects, Rules, ComplexPredicates,
2688
CustomRendererFns, "GET_GICOMBINER_IMPL");
2689
2690
// GET_GICOMBINER_CONSTRUCTOR_INITS, which are in the constructor's
2691
// initializer list.
2692
emitPredicatesInit(OS, "GET_GICOMBINER_CONSTRUCTOR_INITS");
2693
emitTemporariesInit(OS, MaxTemporaries, "GET_GICOMBINER_CONSTRUCTOR_INITS");
2694
}
2695
2696
} // end anonymous namespace
2697
2698
//===----------------------------------------------------------------------===//
2699
2700
static void EmitGICombiner(RecordKeeper &RK, raw_ostream &OS) {
2701
EnablePrettyStackTrace();
2702
CodeGenTarget Target(RK);
2703
2704
if (SelectedCombiners.empty())
2705
PrintFatalError("No combiners selected with -combiners");
2706
for (const auto &Combiner : SelectedCombiners) {
2707
Record *CombinerDef = RK.getDef(Combiner);
2708
if (!CombinerDef)
2709
PrintFatalError("Could not find " + Combiner);
2710
GICombinerEmitter(RK, Target, Combiner, CombinerDef).run(OS);
2711
}
2712
}
2713
2714
static TableGen::Emitter::Opt X("gen-global-isel-combiner", EmitGICombiner,
2715
"Generate GlobalISel Combiner");
2716
2717