Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / llvm / utils / TableGen / GlobalISelCombinerEmitter.cpp
blob0c7b33a7b9d889deee2e61a174dae473b3c12b35
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 //===----------------------------------------------------------------------===//
29 #include "CodeGenInstruction.h"
30 #include "CodeGenTarget.h"
31 #include "GlobalISel/CodeExpander.h"
32 #include "GlobalISel/CodeExpansions.h"
33 #include "GlobalISel/CombinerUtils.h"
34 #include "GlobalISelMatchTable.h"
35 #include "GlobalISelMatchTableExecutorEmitter.h"
36 #include "SubtargetFeatureInfo.h"
37 #include "llvm/ADT/APInt.h"
38 #include "llvm/ADT/Hashing.h"
39 #include "llvm/ADT/MapVector.h"
40 #include "llvm/ADT/Statistic.h"
41 #include "llvm/ADT/StringSet.h"
42 #include "llvm/Support/CommandLine.h"
43 #include "llvm/Support/Debug.h"
44 #include "llvm/Support/PrettyStackTrace.h"
45 #include "llvm/Support/ScopedPrinter.h"
46 #include "llvm/TableGen/Error.h"
47 #include "llvm/TableGen/Record.h"
48 #include "llvm/TableGen/StringMatcher.h"
49 #include "llvm/TableGen/TableGenBackend.h"
50 #include <cstdint>
52 using namespace llvm;
53 using namespace llvm::gi;
55 #define DEBUG_TYPE "gicombiner-emitter"
57 namespace {
58 cl::OptionCategory
59 GICombinerEmitterCat("Options for -gen-global-isel-combiner");
60 cl::opt<bool> StopAfterParse(
61 "gicombiner-stop-after-parse",
62 cl::desc("Stop processing after parsing rules and dump state"),
63 cl::cat(GICombinerEmitterCat));
64 cl::list<std::string>
65 SelectedCombiners("combiners", cl::desc("Emit the specified combiners"),
66 cl::cat(GICombinerEmitterCat), cl::CommaSeparated);
67 cl::opt<bool> DebugCXXPreds(
68 "gicombiner-debug-cxxpreds",
69 cl::desc("Add Contextual/Debug comments to all C++ predicates"),
70 cl::cat(GICombinerEmitterCat));
72 constexpr StringLiteral CXXApplyPrefix = "GICXXCustomAction_CombineApply";
73 constexpr StringLiteral CXXPredPrefix = "GICXXPred_MI_Predicate_";
74 constexpr StringLiteral PatFragClassName = "GICombinePatFrag";
75 constexpr StringLiteral BuiltinInstClassName = "GIBuiltinInst";
76 constexpr StringLiteral SpecialTyClassName = "GISpecialType";
77 constexpr StringLiteral TypeOfClassName = "GITypeOf";
79 std::string getIsEnabledPredicateEnumName(unsigned CombinerRuleID) {
80 return "GICXXPred_Simple_IsRule" + to_string(CombinerRuleID) + "Enabled";
83 /// Copies a StringRef into a static pool to make sure it has a static lifetime.
84 StringRef insertStrRef(StringRef S) {
85 if (S.empty())
86 return {};
88 static StringSet<> Pool;
89 auto [It, Inserted] = Pool.insert(S);
90 return It->getKey();
93 void declareInstExpansion(CodeExpansions &CE, const InstructionMatcher &IM,
94 StringRef Name) {
95 CE.declare(Name, "State.MIs[" + to_string(IM.getInsnVarID()) + "]");
98 void declareInstExpansion(CodeExpansions &CE, const BuildMIAction &A,
99 StringRef Name) {
100 // Note: we use redeclare here because this may overwrite a matcher inst
101 // expansion.
102 CE.redeclare(Name, "OutMIs[" + to_string(A.getInsnID()) + "]");
105 void declareOperandExpansion(CodeExpansions &CE, const OperandMatcher &OM,
106 StringRef Name) {
107 CE.declare(Name, "State.MIs[" + to_string(OM.getInsnVarID()) +
108 "]->getOperand(" + to_string(OM.getOpIdx()) + ")");
111 void declareTempRegExpansion(CodeExpansions &CE, unsigned TempRegID,
112 StringRef Name) {
113 CE.declare(Name, "State.TempRegisters[" + to_string(TempRegID) + "]");
116 std::string makeAnonPatName(StringRef Prefix, unsigned Idx) {
117 return ("__" + Prefix + "_" + Twine(Idx)).str();
120 template <typename Container> auto keys(Container &&C) {
121 return map_range(C, [](auto &Entry) -> auto & { return Entry.first; });
124 template <typename Container> auto values(Container &&C) {
125 return map_range(C, [](auto &Entry) -> auto & { return Entry.second; });
128 //===- MatchData Handling -------------------------------------------------===//
130 /// Represents MatchData defined by the match stage and required by the apply
131 /// stage.
133 /// This allows the plumbing of arbitrary data from C++ predicates between the
134 /// stages.
136 /// When this class is initially created, it only has a pattern symbol and a
137 /// type. When all of the MatchDatas declarations of a given pattern have been
138 /// parsed, `AssignVariables` must be called to assign storage variable names to
139 /// each MatchDataInfo.
140 class MatchDataInfo {
141 StringRef PatternSymbol;
142 StringRef Type;
143 std::string VarName;
145 public:
146 static constexpr StringLiteral StructTypeName = "MatchInfosTy";
147 static constexpr StringLiteral StructName = "MatchInfos";
149 MatchDataInfo(StringRef PatternSymbol, StringRef Type)
150 : PatternSymbol(PatternSymbol), Type(Type.trim()) {}
152 StringRef getPatternSymbol() const { return PatternSymbol; };
153 StringRef getType() const { return Type; };
155 bool hasVariableName() const { return !VarName.empty(); }
156 void setVariableName(StringRef Name) { VarName = Name; }
157 StringRef getVariableName() const;
159 std::string getQualifiedVariableName() const {
160 return StructName.str() + "." + getVariableName().str();
163 void print(raw_ostream &OS) const;
164 void dump() const { print(dbgs()); }
167 StringRef MatchDataInfo::getVariableName() const {
168 assert(hasVariableName());
169 return VarName;
172 void MatchDataInfo::print(raw_ostream &OS) const {
173 OS << "(MatchDataInfo pattern_symbol:" << PatternSymbol << " type:'" << Type
174 << "' var_name:" << (VarName.empty() ? "<unassigned>" : VarName) << ")";
177 /// Pool of type -> variables used to emit MatchData variables declarations.
179 /// e.g. if the map contains "int64_t" -> ["MD0", "MD1"], then two variable
180 /// declarations must be emitted: `int64_t MD0` and `int64_t MD1`.
182 /// This has a static lifetime and will outlive all the `MatchDataInfo` objects
183 /// by design. It needs to persist after all `CombineRuleBuilder` objects died
184 /// so we can emit the variable declarations.
185 StringMap<std::vector<std::string>> AllMatchDataVars;
187 // Assign variable names to all MatchDatas used by a pattern. This must be
188 // called after all MatchData decls have been parsed inside a rule.
190 // Requires an array of MatchDataInfo so we can handle cases where a pattern
191 // uses multiple instances of the same MatchData type.
192 void AssignMatchDataVariables(MutableArrayRef<MatchDataInfo> Infos) {
193 static unsigned NextVarID = 0;
195 StringMap<unsigned> SeenTypes;
196 for (auto &Info : Infos) {
197 unsigned &NumSeen = SeenTypes[Info.getType()];
198 auto &ExistingVars = AllMatchDataVars[Info.getType()];
200 if (NumSeen == ExistingVars.size())
201 ExistingVars.push_back("MDInfo" + to_string(NextVarID++));
203 Info.setVariableName(ExistingVars[NumSeen++]);
207 //===- C++ Predicates Handling --------------------------------------------===//
209 /// Entry into the static pool of all CXX Predicate code. This contains
210 /// fully expanded C++ code.
212 /// The static pool is hidden inside the object and can be accessed through
213 /// getAllMatchCode/getAllApplyCode
215 /// Note that CXXPattern trims C++ code, so the Code is already expected to be
216 /// free of leading/trailing whitespace.
217 class CXXPredicateCode {
218 using CXXPredicateCodePool =
219 DenseMap<hash_code, std::unique_ptr<CXXPredicateCode>>;
220 static CXXPredicateCodePool AllCXXMatchCode;
221 static CXXPredicateCodePool AllCXXApplyCode;
223 /// Sorts a `CXXPredicateCodePool` by their IDs and returns it.
224 static std::vector<const CXXPredicateCode *>
225 getSorted(const CXXPredicateCodePool &Pool) {
226 std::vector<const CXXPredicateCode *> Out;
227 std::transform(Pool.begin(), Pool.end(), std::back_inserter(Out),
228 [&](auto &Elt) { return Elt.second.get(); });
229 sort(Out, [](const auto *A, const auto *B) { return A->ID < B->ID; });
230 return Out;
233 /// Gets an instance of `CXXPredicateCode` for \p Code, or returns an already
234 /// existing one.
235 static const CXXPredicateCode &get(CXXPredicateCodePool &Pool,
236 std::string Code) {
237 // Check if we already have an identical piece of code, if not, create an
238 // entry in the pool.
239 const auto CodeHash = hash_value(Code);
240 if (auto It = Pool.find(CodeHash); It != Pool.end())
241 return *It->second;
243 const auto ID = Pool.size();
244 auto OwnedData = std::unique_ptr<CXXPredicateCode>(
245 new CXXPredicateCode(std::move(Code), ID));
246 const auto &DataRef = *OwnedData;
247 Pool[CodeHash] = std::move(OwnedData);
248 return DataRef;
251 CXXPredicateCode(std::string Code, unsigned ID)
252 : Code(Code), ID(ID), BaseEnumName("GICombiner" + to_string(ID)) {
253 // Don't assert if ErrorsPrinted is set. This may mean CodeExpander failed,
254 // and it may add spaces in such cases.
255 assert((ErrorsPrinted || StringRef(Code).trim() == Code) &&
256 "Code was expected to be trimmed!");
259 public:
260 static const CXXPredicateCode &getMatchCode(std::string Code) {
261 return get(AllCXXMatchCode, std::move(Code));
264 static const CXXPredicateCode &getApplyCode(std::string Code) {
265 return get(AllCXXApplyCode, std::move(Code));
268 static std::vector<const CXXPredicateCode *> getAllMatchCode() {
269 return getSorted(AllCXXMatchCode);
272 static std::vector<const CXXPredicateCode *> getAllApplyCode() {
273 return getSorted(AllCXXApplyCode);
276 const std::string Code;
277 const unsigned ID;
278 const std::string BaseEnumName;
280 bool needsUnreachable() const {
281 return !StringRef(Code).starts_with("return");
284 std::string getEnumNameWithPrefix(StringRef Prefix) const {
285 return Prefix.str() + BaseEnumName;
289 CXXPredicateCode::CXXPredicateCodePool CXXPredicateCode::AllCXXMatchCode;
290 CXXPredicateCode::CXXPredicateCodePool CXXPredicateCode::AllCXXApplyCode;
292 //===- PatternType --------------------------------------------------------===//
294 /// Represent the type of a Pattern Operand.
296 /// Types have two form:
297 /// - LLTs, which are straightforward.
298 /// - Special types, e.g. GITypeOf
299 class PatternType {
300 public:
301 PatternType() = default;
302 PatternType(const Record *R) : R(R) {}
304 bool isValidType() const { return !R || isLLT() || isSpecial(); }
306 bool isLLT() const { return R && R->isSubClassOf("ValueType"); }
307 bool isSpecial() const { return R && R->isSubClassOf(SpecialTyClassName); }
308 bool isTypeOf() const { return R && R->isSubClassOf(TypeOfClassName); }
310 StringRef getTypeOfOpName() const;
311 LLTCodeGen getLLTCodeGen() const;
313 bool checkSemantics(ArrayRef<SMLoc> DiagLoc) const;
315 LLTCodeGenOrTempType getLLTCodeGenOrTempType(RuleMatcher &RM) const;
317 explicit operator bool() const { return R != nullptr; }
319 bool operator==(const PatternType &Other) const;
320 bool operator!=(const PatternType &Other) const { return !operator==(Other); }
322 std::string str() const;
324 private:
325 StringRef getRawOpName() const { return R->getValueAsString("OpName"); }
327 const Record *R = nullptr;
330 StringRef PatternType::getTypeOfOpName() const {
331 assert(isTypeOf());
332 StringRef Name = getRawOpName();
333 Name.consume_front("$");
334 return Name;
337 LLTCodeGen PatternType::getLLTCodeGen() const {
338 assert(isLLT());
339 return *MVTToLLT(getValueType(R));
342 LLTCodeGenOrTempType
343 PatternType::getLLTCodeGenOrTempType(RuleMatcher &RM) const {
344 assert(isValidType());
346 if (isLLT())
347 return getLLTCodeGen();
349 assert(isTypeOf());
350 auto &OM = RM.getOperandMatcher(getTypeOfOpName());
351 return OM.getTempTypeIdx(RM);
354 bool PatternType::checkSemantics(ArrayRef<SMLoc> DiagLoc) const {
355 if (!isTypeOf())
356 return true;
358 auto RawOpName = getRawOpName();
359 if (RawOpName.starts_with("$"))
360 return true;
362 PrintError(DiagLoc, "invalid operand name format '" + RawOpName + "' in " +
363 TypeOfClassName +
364 ": expected '$' followed by an operand name");
365 return false;
368 bool PatternType::operator==(const PatternType &Other) const {
369 if (R == Other.R) {
370 if (R && R->getName() != Other.R->getName()) {
371 dbgs() << "Same ptr but: " << R->getName() << " and "
372 << Other.R->getName() << "?\n";
373 assert(false);
375 return true;
378 if (isTypeOf() && Other.isTypeOf())
379 return getTypeOfOpName() == Other.getTypeOfOpName();
381 return false;
384 std::string PatternType::str() const {
385 if (!R)
386 return "";
388 if (!isValidType())
389 return "<invalid>";
391 if (isLLT())
392 return R->getName().str();
394 assert(isSpecial());
396 if (isTypeOf())
397 return (TypeOfClassName + "<$" + getTypeOfOpName() + ">").str();
399 llvm_unreachable("Unknown type!");
402 //===- Pattern Base Class -------------------------------------------------===//
404 /// Base class for all patterns that can be written in an `apply`, `match` or
405 /// `pattern` DAG operator.
407 /// For example:
409 /// (apply (G_ZEXT $x, $y), (G_ZEXT $y, $z), "return isFoo(${z})")
411 /// Creates 3 Pattern objects:
412 /// - Two CodeGenInstruction Patterns
413 /// - A CXXPattern
414 class Pattern {
415 public:
416 enum {
417 K_AnyOpcode,
418 K_CXX,
420 K_CodeGenInstruction,
421 K_PatFrag,
422 K_Builtin,
425 virtual ~Pattern() = default;
427 unsigned getKind() const { return Kind; }
428 const char *getKindName() const;
430 bool hasName() const { return !Name.empty(); }
431 StringRef getName() const { return Name; }
433 virtual void print(raw_ostream &OS, bool PrintName = true) const = 0;
434 void dump() const { return print(dbgs()); }
436 protected:
437 Pattern(unsigned Kind, StringRef Name)
438 : Kind(Kind), Name(insertStrRef(Name)) {
439 assert(!Name.empty() && "unnamed pattern!");
442 void printImpl(raw_ostream &OS, bool PrintName,
443 function_ref<void()> ContentPrinter) const;
445 private:
446 unsigned Kind;
447 StringRef Name;
450 const char *Pattern::getKindName() const {
451 switch (Kind) {
452 case K_AnyOpcode:
453 return "AnyOpcodePattern";
454 case K_CXX:
455 return "CXXPattern";
456 case K_CodeGenInstruction:
457 return "CodeGenInstructionPattern";
458 case K_PatFrag:
459 return "PatFragPattern";
460 case K_Builtin:
461 return "BuiltinPattern";
464 llvm_unreachable("unknown pattern kind!");
467 void Pattern::printImpl(raw_ostream &OS, bool PrintName,
468 function_ref<void()> ContentPrinter) const {
469 OS << "(" << getKindName() << " ";
470 if (PrintName)
471 OS << "name:" << getName() << " ";
472 ContentPrinter();
473 OS << ")";
476 //===- AnyOpcodePattern ---------------------------------------------------===//
478 /// `wip_match_opcode` patterns.
479 /// This matches one or more opcodes, and does not check any operands
480 /// whatsoever.
482 /// TODO: Long-term, this needs to be removed. It's a hack around MIR
483 /// pattern matching limitations.
484 class AnyOpcodePattern : public Pattern {
485 public:
486 AnyOpcodePattern(StringRef Name) : Pattern(K_AnyOpcode, Name) {}
488 static bool classof(const Pattern *P) { return P->getKind() == K_AnyOpcode; }
490 void addOpcode(const CodeGenInstruction *I) { Insts.push_back(I); }
491 const auto &insts() const { return Insts; }
493 void print(raw_ostream &OS, bool PrintName = true) const override;
495 private:
496 SmallVector<const CodeGenInstruction *, 4> Insts;
499 void AnyOpcodePattern::print(raw_ostream &OS, bool PrintName) const {
500 printImpl(OS, PrintName, [&OS, this]() {
501 OS << "["
502 << join(map_range(Insts,
503 [](const auto *I) { return I->TheDef->getName(); }),
504 ", ")
505 << "]";
509 //===- CXXPattern ---------------------------------------------------------===//
511 /// Represents raw C++ code which may need some expansions.
513 /// e.g. [{ return isFooBux(${src}.getReg()); }]
515 /// For the expanded code, \see CXXPredicateCode. CXXPredicateCode objects are
516 /// created through `expandCode`.
518 /// \see CodeExpander and \see CodeExpansions for more information on code
519 /// expansions.
521 /// This object has two purposes:
522 /// - Represent C++ code as a pattern entry.
523 /// - Be a factory for expanded C++ code.
524 /// - It's immutable and only holds the raw code so we can expand the same
525 /// CXX pattern multiple times if we need to.
527 /// Note that the code is always trimmed in the constructor, so leading and
528 /// trailing whitespaces are removed. This removes bloat in the output, avoids
529 /// formatting issues, but also allows us to check things like
530 /// `.startswith("return")` trivially without worrying about spaces.
531 class CXXPattern : public Pattern {
532 public:
533 CXXPattern(const StringInit &Code, StringRef Name)
534 : CXXPattern(Code.getAsUnquotedString(), Name) {}
536 CXXPattern(StringRef Code, StringRef Name)
537 : Pattern(K_CXX, Name), RawCode(Code.trim().str()) {}
539 static bool classof(const Pattern *P) { return P->getKind() == K_CXX; }
541 void setIsApply(bool Value = true) { IsApply = Value; }
542 StringRef getRawCode() const { return RawCode; }
544 /// Expands raw code, replacing things such as `${foo}` with their
545 /// substitution in \p CE.
547 /// \param CE Map of Code Expansions
548 /// \param Locs SMLocs for the Code Expander, in case it needs to emit
549 /// diagnostics.
550 /// \param AddComment If DebugCXXPreds is enabled, this is called to emit a
551 /// comment before the expanded code.
553 /// \return A CXXPredicateCode object that contains the expanded code. Note
554 /// that this may or may not insert a new object. All CXXPredicateCode objects
555 /// are held in a set to avoid emitting duplicate C++ code.
556 const CXXPredicateCode &
557 expandCode(const CodeExpansions &CE, ArrayRef<SMLoc> Locs,
558 function_ref<void(raw_ostream &)> AddComment = {}) const;
560 void print(raw_ostream &OS, bool PrintName = true) const override;
562 private:
563 bool IsApply = false;
564 std::string RawCode;
567 const CXXPredicateCode &
568 CXXPattern::expandCode(const CodeExpansions &CE, ArrayRef<SMLoc> Locs,
569 function_ref<void(raw_ostream &)> AddComment) const {
570 std::string Result;
571 raw_string_ostream OS(Result);
573 if (DebugCXXPreds && AddComment)
574 AddComment(OS);
576 CodeExpander Expander(RawCode, CE, Locs, /*ShowExpansions*/ false);
577 Expander.emit(OS);
578 if (IsApply)
579 return CXXPredicateCode::getApplyCode(std::move(Result));
580 return CXXPredicateCode::getMatchCode(std::move(Result));
583 void CXXPattern::print(raw_ostream &OS, bool PrintName) const {
584 printImpl(OS, PrintName, [&OS, this] {
585 OS << (IsApply ? "apply" : "match") << " code:\"";
586 printEscapedString(getRawCode(), OS);
587 OS << "\"";
591 //===- InstructionPattern ---------------------------------------------===//
593 /// An operand for an InstructionPattern.
595 /// Operands are composed of three elements:
596 /// - (Optional) Value
597 /// - (Optional) Name
598 /// - (Optional) Type
600 /// Some examples:
601 /// (i32 0):$x -> V=int(0), Name='x', Type=i32
602 /// 0:$x -> V=int(0), Name='x'
603 /// $x -> Name='x'
604 /// i32:$x -> Name='x', Type = i32
605 class InstructionOperand {
606 public:
607 using IntImmTy = int64_t;
609 InstructionOperand(IntImmTy Imm, StringRef Name, PatternType Type)
610 : Value(Imm), Name(insertStrRef(Name)), Type(Type) {
611 assert(Type.isValidType());
614 InstructionOperand(StringRef Name, PatternType Type)
615 : Name(insertStrRef(Name)), Type(Type) {
616 assert(Type.isValidType());
619 bool isNamedImmediate() const { return hasImmValue() && isNamedOperand(); }
621 bool hasImmValue() const { return Value.has_value(); }
622 IntImmTy getImmValue() const { return *Value; }
624 bool isNamedOperand() const { return !Name.empty(); }
625 StringRef getOperandName() const {
626 assert(isNamedOperand() && "Operand is unnamed");
627 return Name;
630 InstructionOperand withNewName(StringRef NewName) const {
631 InstructionOperand Result = *this;
632 Result.Name = insertStrRef(NewName);
633 return Result;
636 void setIsDef(bool Value = true) { Def = Value; }
637 bool isDef() const { return Def; }
639 void setType(PatternType NewType) {
640 assert((!Type || (Type == NewType)) && "Overwriting type!");
641 assert(NewType.isValidType());
642 Type = NewType;
644 PatternType getType() const { return Type; }
646 std::string describe() const {
647 if (!hasImmValue())
648 return "MachineOperand $" + getOperandName().str() + "";
649 std::string Str = "imm " + to_string(getImmValue());
650 if (isNamedImmediate())
651 Str += ":$" + getOperandName().str() + "";
652 return Str;
655 void print(raw_ostream &OS) const {
656 if (isDef())
657 OS << "<def>";
659 bool NeedsColon = true;
660 if (Type) {
661 if (hasImmValue())
662 OS << "(" << Type.str() << " " << getImmValue() << ")";
663 else
664 OS << Type.str();
665 } else if (hasImmValue())
666 OS << getImmValue();
667 else
668 NeedsColon = false;
670 if (isNamedOperand())
671 OS << (NeedsColon ? ":" : "") << "$" << getOperandName();
674 void dump() const { return print(dbgs()); }
676 private:
677 std::optional<int64_t> Value;
678 StringRef Name;
679 PatternType Type;
680 bool Def = false;
683 /// Base class for CodeGenInstructionPattern & PatFragPattern, which handles all
684 /// the boilerplate for patterns that have a list of operands for some (pseudo)
685 /// instruction.
686 class InstructionPattern : public Pattern {
687 public:
688 virtual ~InstructionPattern() = default;
690 static bool classof(const Pattern *P) {
691 return P->getKind() == K_CodeGenInstruction || P->getKind() == K_PatFrag ||
692 P->getKind() == K_Builtin;
695 template <typename... Ty> void addOperand(Ty &&...Init) {
696 Operands.emplace_back(std::forward<Ty>(Init)...);
699 auto &operands() { return Operands; }
700 const auto &operands() const { return Operands; }
701 unsigned operands_size() const { return Operands.size(); }
702 InstructionOperand &getOperand(unsigned K) { return Operands[K]; }
703 const InstructionOperand &getOperand(unsigned K) const { return Operands[K]; }
705 /// When this InstructionPattern is used as the match root, returns the
706 /// operands that must be redefined in the 'apply' pattern for the rule to be
707 /// valid.
709 /// For most patterns, this just returns the defs.
710 /// For PatFrag this only returns the root of the PF.
712 /// Returns an empty array on error.
713 virtual ArrayRef<InstructionOperand> getApplyDefsNeeded() const {
714 return {operands().begin(), getNumInstDefs()};
717 auto named_operands() {
718 return make_filter_range(Operands,
719 [&](auto &O) { return O.isNamedOperand(); });
722 auto named_operands() const {
723 return make_filter_range(Operands,
724 [&](auto &O) { return O.isNamedOperand(); });
727 virtual bool isVariadic() const { return false; }
728 virtual unsigned getNumInstOperands() const = 0;
729 virtual unsigned getNumInstDefs() const = 0;
731 bool hasAllDefs() const { return operands_size() >= getNumInstDefs(); }
733 virtual StringRef getInstName() const = 0;
735 /// Diagnoses all uses of special types in this Pattern and returns true if at
736 /// least one diagnostic was emitted.
737 bool diagnoseAllSpecialTypes(ArrayRef<SMLoc> Loc, Twine Msg) const;
739 void reportUnreachable(ArrayRef<SMLoc> Locs) const;
740 virtual bool checkSemantics(ArrayRef<SMLoc> Loc);
742 void print(raw_ostream &OS, bool PrintName = true) const override;
744 protected:
745 InstructionPattern(unsigned K, StringRef Name) : Pattern(K, Name) {}
747 SmallVector<InstructionOperand, 4> Operands;
750 bool InstructionPattern::diagnoseAllSpecialTypes(ArrayRef<SMLoc> Loc,
751 Twine Msg) const {
752 bool HasDiag = false;
753 for (const auto &[Idx, Op] : enumerate(operands())) {
754 if (Op.getType().isSpecial()) {
755 PrintError(Loc, Msg);
756 PrintNote(Loc, "operand " + Twine(Idx) + " of '" + getName() +
757 "' has type '" + Op.getType().str() + "'");
758 HasDiag = true;
761 return HasDiag;
764 void InstructionPattern::reportUnreachable(ArrayRef<SMLoc> Locs) const {
765 PrintError(Locs, "pattern '" + getName() + "' ('" + getInstName() +
766 "') is unreachable from the pattern root!");
769 bool InstructionPattern::checkSemantics(ArrayRef<SMLoc> Loc) {
770 unsigned NumExpectedOperands = getNumInstOperands();
772 if (isVariadic()) {
773 if (Operands.size() < NumExpectedOperands) {
774 PrintError(Loc, +"'" + getInstName() + "' expected at least " +
775 Twine(NumExpectedOperands) + " operands, got " +
776 Twine(Operands.size()));
777 return false;
779 } else if (NumExpectedOperands != Operands.size()) {
780 PrintError(Loc, +"'" + getInstName() + "' expected " +
781 Twine(NumExpectedOperands) + " operands, got " +
782 Twine(Operands.size()));
783 return false;
786 unsigned OpIdx = 0;
787 unsigned NumDefs = getNumInstDefs();
788 for (auto &Op : Operands)
789 Op.setIsDef(OpIdx++ < NumDefs);
791 return true;
794 void InstructionPattern::print(raw_ostream &OS, bool PrintName) const {
795 printImpl(OS, PrintName, [&OS, this] {
796 OS << getInstName() << " operands:[";
797 StringRef Sep = "";
798 for (const auto &Op : Operands) {
799 OS << Sep;
800 Op.print(OS);
801 Sep = ", ";
803 OS << "]";
807 //===- OperandTable -------------------------------------------------------===//
809 /// Maps InstructionPattern operands to their definitions. This allows us to tie
810 /// different patterns of a (apply), (match) or (patterns) set of patterns
811 /// together.
812 template <typename DefTy = InstructionPattern> class OperandTable {
813 public:
814 static_assert(std::is_base_of_v<InstructionPattern, DefTy>,
815 "DefTy should be a derived class from InstructionPattern");
817 bool addPattern(DefTy *P, function_ref<void(StringRef)> DiagnoseRedef) {
818 for (const auto &Op : P->named_operands()) {
819 StringRef OpName = Op.getOperandName();
821 // We always create an entry in the OperandTable, even for uses.
822 // Uses of operands that don't have a def (= live-ins) will remain with a
823 // nullptr as the Def.
825 // This allows us tell whether an operand exists in a pattern or not. If
826 // there is no entry for it, it doesn't exist, if there is an entry, it's
827 // used/def'd at least once.
828 auto &Def = Table[OpName];
830 if (!Op.isDef())
831 continue;
833 if (Def) {
834 DiagnoseRedef(OpName);
835 return false;
838 Def = P;
841 return true;
844 struct LookupResult {
845 LookupResult() = default;
846 LookupResult(DefTy *Def) : Found(true), Def(Def) {}
848 bool Found = false;
849 DefTy *Def = nullptr;
851 bool isLiveIn() const { return Found && !Def; }
854 LookupResult lookup(StringRef OpName) const {
855 if (auto It = Table.find(OpName); It != Table.end())
856 return LookupResult(It->second);
857 return LookupResult();
860 DefTy *getDef(StringRef OpName) const { return lookup(OpName).Def; }
862 void print(raw_ostream &OS, StringRef Name = "",
863 StringRef Indent = "") const {
864 OS << Indent << "(OperandTable ";
865 if (!Name.empty())
866 OS << Name << " ";
867 if (Table.empty()) {
868 OS << "<empty>)\n";
869 return;
872 SmallVector<StringRef, 0> Keys(Table.keys());
873 sort(Keys);
875 OS << "\n";
876 for (const auto &Key : Keys) {
877 const auto *Def = Table.at(Key);
878 OS << Indent << " " << Key << " -> "
879 << (Def ? Def->getName() : "<live-in>") << "\n";
881 OS << Indent << ")\n";
884 auto begin() const { return Table.begin(); }
885 auto end() const { return Table.end(); }
887 void dump() const { print(dbgs()); }
889 private:
890 StringMap<DefTy *> Table;
893 //===- CodeGenInstructionPattern ------------------------------------------===//
895 /// Matches an instruction, e.g. `G_ADD $x, $y, $z`.
896 class CodeGenInstructionPattern : public InstructionPattern {
897 public:
898 CodeGenInstructionPattern(const CodeGenInstruction &I, StringRef Name)
899 : InstructionPattern(K_CodeGenInstruction, Name), I(I) {}
901 static bool classof(const Pattern *P) {
902 return P->getKind() == K_CodeGenInstruction;
905 bool is(StringRef OpcodeName) const {
906 return I.TheDef->getName() == OpcodeName;
909 bool hasVariadicDefs() const;
910 bool isVariadic() const override { return I.Operands.isVariadic; }
911 unsigned getNumInstDefs() const override;
912 unsigned getNumInstOperands() const override;
914 const CodeGenInstruction &getInst() const { return I; }
915 StringRef getInstName() const override { return I.TheDef->getName(); }
917 private:
918 const CodeGenInstruction &I;
921 bool CodeGenInstructionPattern::hasVariadicDefs() const {
922 // Note: we cannot use variadicOpsAreDefs, it's not set for
923 // GenericInstructions.
924 if (!isVariadic())
925 return false;
927 if (I.variadicOpsAreDefs)
928 return true;
930 DagInit *OutOps = I.TheDef->getValueAsDag("OutOperandList");
931 if (OutOps->arg_empty())
932 return false;
934 auto *LastArgTy = dyn_cast<DefInit>(OutOps->getArg(OutOps->arg_size() - 1));
935 return LastArgTy && LastArgTy->getDef()->getName() == "variable_ops";
938 unsigned CodeGenInstructionPattern::getNumInstDefs() const {
939 if (!isVariadic() || !hasVariadicDefs())
940 return I.Operands.NumDefs;
941 unsigned NumOuts = I.Operands.size() - I.Operands.NumDefs;
942 assert(Operands.size() > NumOuts);
943 return std::max<unsigned>(I.Operands.NumDefs, Operands.size() - NumOuts);
946 unsigned CodeGenInstructionPattern::getNumInstOperands() const {
947 unsigned NumCGIOps = I.Operands.size();
948 return isVariadic() ? std::max<unsigned>(NumCGIOps, Operands.size())
949 : NumCGIOps;
952 //===- OperandTypeChecker -------------------------------------------------===//
954 /// This is a trivial type checker for all operands in a set of
955 /// InstructionPatterns.
957 /// It infers the type of each operand, check it's consistent with the known
958 /// type of the operand, and then sets all of the types in all operands in
959 /// setAllOperandTypes.
961 /// It also handles verifying correctness of special types.
962 class OperandTypeChecker {
963 public:
964 OperandTypeChecker(ArrayRef<SMLoc> DiagLoc) : DiagLoc(DiagLoc) {}
966 bool check(InstructionPattern *P,
967 std::function<bool(const PatternType &)> VerifyTypeOfOperand);
969 void setAllOperandTypes();
971 private:
972 struct OpTypeInfo {
973 PatternType Type;
974 InstructionPattern *TypeSrc = nullptr;
977 ArrayRef<SMLoc> DiagLoc;
978 StringMap<OpTypeInfo> Types;
980 SmallVector<InstructionPattern *, 16> Pats;
983 bool OperandTypeChecker::check(
984 InstructionPattern *P,
985 std::function<bool(const PatternType &)> VerifyTypeOfOperand) {
986 Pats.push_back(P);
988 for (auto &Op : P->operands()) {
989 const auto Ty = Op.getType();
990 if (!Ty)
991 continue;
993 if (!Ty.checkSemantics(DiagLoc))
994 return false;
996 if (Ty.isTypeOf() && !VerifyTypeOfOperand(Ty))
997 return false;
999 if (!Op.isNamedOperand())
1000 continue;
1002 auto &Info = Types[Op.getOperandName()];
1003 if (!Info.Type) {
1004 Info.Type = Ty;
1005 Info.TypeSrc = P;
1006 continue;
1009 if (Info.Type != Ty) {
1010 PrintError(DiagLoc, "conflicting types for operand '" +
1011 Op.getOperandName() + "': first seen with '" +
1012 Info.Type.str() + "' in '" +
1013 Info.TypeSrc->getName() + ", now seen with '" +
1014 Ty.str() + "' in '" + P->getName() + "'");
1015 return false;
1019 return true;
1022 void OperandTypeChecker::setAllOperandTypes() {
1023 for (auto *Pat : Pats) {
1024 for (auto &Op : Pat->named_operands()) {
1025 if (auto &Info = Types[Op.getOperandName()]; Info.Type)
1026 Op.setType(Info.Type);
1031 //===- PatFrag ------------------------------------------------------------===//
1033 /// Represents a parsed GICombinePatFrag. This can be thought of as the
1034 /// equivalent of a CodeGenInstruction, but for PatFragPatterns.
1036 /// PatFrags are made of 3 things:
1037 /// - Out parameters (defs)
1038 /// - In parameters
1039 /// - A set of pattern lists (alternatives).
1041 /// If the PatFrag uses instruction patterns, the root must be one of the defs.
1043 /// Note that this DOES NOT represent the use of the PatFrag, only its
1044 /// definition. The use of the PatFrag in a Pattern is represented by
1045 /// PatFragPattern.
1047 /// PatFrags use the term "parameter" instead of operand because they're
1048 /// essentially macros, and using that name avoids confusion. Other than that,
1049 /// they're structured similarly to a MachineInstruction - all parameters
1050 /// (operands) are in the same list, with defs at the start. This helps mapping
1051 /// parameters to values, because, param N of a PatFrag is always operand N of a
1052 /// PatFragPattern.
1053 class PatFrag {
1054 public:
1055 enum ParamKind {
1056 PK_Root,
1057 PK_MachineOperand,
1058 PK_Imm,
1061 struct Param {
1062 StringRef Name;
1063 ParamKind Kind;
1066 using ParamVec = SmallVector<Param, 4>;
1067 using ParamIt = ParamVec::const_iterator;
1069 /// Represents an alternative of the PatFrag. When parsing a GICombinePatFrag,
1070 /// this is created from its "Alternatives" list. Each alternative is a list
1071 /// of patterns written wrapped in a `(pattern ...)` dag init.
1073 /// Each argument to the `pattern` DAG operator is parsed into a Pattern
1074 /// instance.
1075 struct Alternative {
1076 OperandTable<> OpTable;
1077 SmallVector<std::unique_ptr<Pattern>, 4> Pats;
1080 explicit PatFrag(const Record &Def) : Def(Def) {
1081 assert(Def.isSubClassOf(PatFragClassName));
1084 static StringRef getParamKindStr(ParamKind OK);
1086 StringRef getName() const { return Def.getName(); }
1088 const Record &getDef() const { return Def; }
1089 ArrayRef<SMLoc> getLoc() const { return Def.getLoc(); }
1091 Alternative &addAlternative() { return Alts.emplace_back(); }
1092 const Alternative &getAlternative(unsigned K) const { return Alts[K]; }
1093 unsigned num_alternatives() const { return Alts.size(); }
1095 void addInParam(StringRef Name, ParamKind Kind);
1096 iterator_range<ParamIt> in_params() const;
1097 unsigned num_in_params() const { return Params.size() - NumOutParams; }
1099 void addOutParam(StringRef Name, ParamKind Kind);
1100 iterator_range<ParamIt> out_params() const;
1101 unsigned num_out_params() const { return NumOutParams; }
1103 unsigned num_roots() const;
1104 unsigned num_params() const { return num_in_params() + num_out_params(); }
1106 /// Finds the operand \p Name and returns its index or -1 if not found.
1107 /// Remember that all params are part of the same list, with out params at the
1108 /// start. This means that the index returned can be used to access operands
1109 /// of InstructionPatterns.
1110 unsigned getParamIdx(StringRef Name) const;
1111 const Param &getParam(unsigned K) const { return Params[K]; }
1113 bool canBeMatchRoot() const { return num_roots() == 1; }
1115 void print(raw_ostream &OS, StringRef Indent = "") const;
1116 void dump() const { print(dbgs()); }
1118 /// Checks if the in-param \p ParamName can be unbound or not.
1119 /// \p ArgName is the name of the argument passed to the PatFrag.
1121 /// An argument can be unbound only if, for all alternatives:
1122 /// - There is no CXX pattern, OR:
1123 /// - There is an InstructionPattern that binds the parameter.
1125 /// e.g. in (MyPatFrag $foo), if $foo has never been seen before (= it's
1126 /// unbound), this checks if MyPatFrag supports it or not.
1127 bool handleUnboundInParam(StringRef ParamName, StringRef ArgName,
1128 ArrayRef<SMLoc> DiagLoc) const;
1130 bool checkSemantics();
1131 bool buildOperandsTables();
1133 private:
1134 static void printParamsList(raw_ostream &OS, iterator_range<ParamIt> Params);
1136 void PrintError(Twine Msg) const { ::PrintError(&Def, Msg); }
1138 const Record &Def;
1139 unsigned NumOutParams = 0;
1140 ParamVec Params;
1141 SmallVector<Alternative, 2> Alts;
1144 StringRef PatFrag::getParamKindStr(ParamKind OK) {
1145 switch (OK) {
1146 case PK_Root:
1147 return "root";
1148 case PK_MachineOperand:
1149 return "machine_operand";
1150 case PK_Imm:
1151 return "imm";
1154 llvm_unreachable("Unknown operand kind!");
1157 void PatFrag::addInParam(StringRef Name, ParamKind Kind) {
1158 Params.emplace_back(Param{insertStrRef(Name), Kind});
1161 iterator_range<PatFrag::ParamIt> PatFrag::in_params() const {
1162 return {Params.begin() + NumOutParams, Params.end()};
1165 void PatFrag::addOutParam(StringRef Name, ParamKind Kind) {
1166 assert(NumOutParams == Params.size() &&
1167 "Adding out-param after an in-param!");
1168 Params.emplace_back(Param{insertStrRef(Name), Kind});
1169 ++NumOutParams;
1172 iterator_range<PatFrag::ParamIt> PatFrag::out_params() const {
1173 return {Params.begin(), Params.begin() + NumOutParams};
1176 unsigned PatFrag::num_roots() const {
1177 return count_if(out_params(),
1178 [&](const auto &P) { return P.Kind == PK_Root; });
1181 unsigned PatFrag::getParamIdx(StringRef Name) const {
1182 for (const auto &[Idx, Op] : enumerate(Params)) {
1183 if (Op.Name == Name)
1184 return Idx;
1187 return -1;
1190 bool PatFrag::checkSemantics() {
1191 for (const auto &Alt : Alts) {
1192 for (const auto &Pat : Alt.Pats) {
1193 switch (Pat->getKind()) {
1194 case Pattern::K_AnyOpcode:
1195 PrintError("wip_match_opcode cannot be used in " + PatFragClassName);
1196 return false;
1197 case Pattern::K_Builtin:
1198 PrintError("Builtin instructions cannot be used in " +
1199 PatFragClassName);
1200 return false;
1201 case Pattern::K_CXX:
1202 continue;
1203 case Pattern::K_CodeGenInstruction:
1204 if (cast<CodeGenInstructionPattern>(Pat.get())->diagnoseAllSpecialTypes(
1205 Def.getLoc(), SpecialTyClassName + " is not supported in " +
1206 PatFragClassName))
1207 return false;
1208 continue;
1209 case Pattern::K_PatFrag:
1210 // TODO: It's just that the emitter doesn't handle it but technically
1211 // there is no reason why we can't. We just have to be careful with
1212 // operand mappings, it could get complex.
1213 PrintError("nested " + PatFragClassName + " are not supported");
1214 return false;
1219 StringSet<> SeenOps;
1220 for (const auto &Op : in_params()) {
1221 if (SeenOps.count(Op.Name)) {
1222 PrintError("duplicate parameter '" + Op.Name + "'");
1223 return false;
1226 // Check this operand is NOT defined in any alternative's patterns.
1227 for (const auto &Alt : Alts) {
1228 if (Alt.OpTable.lookup(Op.Name).Def) {
1229 PrintError("input parameter '" + Op.Name + "' cannot be redefined!");
1230 return false;
1234 if (Op.Kind == PK_Root) {
1235 PrintError("input parameterr '" + Op.Name + "' cannot be a root!");
1236 return false;
1239 SeenOps.insert(Op.Name);
1242 for (const auto &Op : out_params()) {
1243 if (Op.Kind != PK_Root && Op.Kind != PK_MachineOperand) {
1244 PrintError("output parameter '" + Op.Name +
1245 "' must be 'root' or 'gi_mo'");
1246 return false;
1249 if (SeenOps.count(Op.Name)) {
1250 PrintError("duplicate parameter '" + Op.Name + "'");
1251 return false;
1254 // Check this operand is defined in all alternative's patterns.
1255 for (const auto &Alt : Alts) {
1256 const auto *OpDef = Alt.OpTable.getDef(Op.Name);
1257 if (!OpDef) {
1258 PrintError("output parameter '" + Op.Name +
1259 "' must be defined by all alternative patterns in '" +
1260 Def.getName() + "'");
1261 return false;
1264 if (Op.Kind == PK_Root && OpDef->getNumInstDefs() != 1) {
1265 // The instruction that defines the root must have a single def.
1266 // Otherwise we'd need to support multiple roots and it gets messy.
1268 // e.g. this is not supported:
1269 // (pattern (G_UNMERGE_VALUES $x, $root, $vec))
1270 PrintError("all instructions that define root '" + Op.Name + "' in '" +
1271 Def.getName() + "' can only have a single output operand");
1272 return false;
1276 SeenOps.insert(Op.Name);
1279 if (num_out_params() != 0 && num_roots() == 0) {
1280 PrintError(PatFragClassName + " must have one root in its 'out' operands");
1281 return false;
1284 if (num_roots() > 1) {
1285 PrintError(PatFragClassName + " can only have one root");
1286 return false;
1289 // TODO: find unused params
1291 const auto CheckTypeOf = [&](const PatternType &) -> bool {
1292 llvm_unreachable("GITypeOf should have been rejected earlier!");
1295 // Now, typecheck all alternatives.
1296 for (auto &Alt : Alts) {
1297 OperandTypeChecker OTC(Def.getLoc());
1298 for (auto &Pat : Alt.Pats) {
1299 if (auto *IP = dyn_cast<InstructionPattern>(Pat.get())) {
1300 if (!OTC.check(IP, CheckTypeOf))
1301 return false;
1304 OTC.setAllOperandTypes();
1307 return true;
1310 bool PatFrag::handleUnboundInParam(StringRef ParamName, StringRef ArgName,
1311 ArrayRef<SMLoc> DiagLoc) const {
1312 // The parameter must be a live-in of all alternatives for this to work.
1313 // Otherwise, we risk having unbound parameters being used (= crashes).
1315 // Examples:
1317 // in (ins $y), (patterns (G_FNEG $dst, $y), "return matchFnegOp(${y})")
1318 // even if $y is unbound, we'll lazily bind it when emitting the G_FNEG.
1320 // in (ins $y), (patterns "return matchFnegOp(${y})")
1321 // if $y is unbound when this fragment is emitted, C++ code expansion will
1322 // fail.
1323 for (const auto &Alt : Alts) {
1324 auto &OT = Alt.OpTable;
1325 if (!OT.lookup(ParamName).Found) {
1326 ::PrintError(DiagLoc, "operand '" + ArgName + "' (for parameter '" +
1327 ParamName + "' of '" + getName() +
1328 "') cannot be unbound");
1329 PrintNote(
1330 DiagLoc,
1331 "one or more alternatives of '" + getName() + "' do not bind '" +
1332 ParamName +
1333 "' to an instruction operand; either use a bound operand or "
1334 "ensure '" +
1335 Def.getName() + "' binds '" + ParamName +
1336 "' in all alternatives");
1337 return false;
1341 return true;
1344 bool PatFrag::buildOperandsTables() {
1345 // enumerate(...) doesn't seem to allow lvalues so we need to count the old
1346 // way.
1347 unsigned Idx = 0;
1349 const auto DiagnoseRedef = [this, &Idx](StringRef OpName) {
1350 PrintError("Operand '" + OpName +
1351 "' is defined multiple times in patterns of alternative #" +
1352 to_string(Idx));
1355 for (auto &Alt : Alts) {
1356 for (auto &Pat : Alt.Pats) {
1357 auto *IP = dyn_cast<InstructionPattern>(Pat.get());
1358 if (!IP)
1359 continue;
1361 if (!Alt.OpTable.addPattern(IP, DiagnoseRedef))
1362 return false;
1365 ++Idx;
1368 return true;
1371 void PatFrag::print(raw_ostream &OS, StringRef Indent) const {
1372 OS << Indent << "(PatFrag name:" << getName() << "\n";
1373 if (!in_params().empty()) {
1374 OS << Indent << " (ins ";
1375 printParamsList(OS, in_params());
1376 OS << ")\n";
1379 if (!out_params().empty()) {
1380 OS << Indent << " (outs ";
1381 printParamsList(OS, out_params());
1382 OS << ")\n";
1385 // TODO: Dump OperandTable as well.
1386 OS << Indent << " (alternatives [\n";
1387 for (const auto &Alt : Alts) {
1388 OS << Indent << " [\n";
1389 for (const auto &Pat : Alt.Pats) {
1390 OS << Indent << " ";
1391 Pat->print(OS, /*PrintName=*/true);
1392 OS << ",\n";
1394 OS << Indent << " ],\n";
1396 OS << Indent << " ])\n";
1398 OS << Indent << ')';
1401 void PatFrag::printParamsList(raw_ostream &OS, iterator_range<ParamIt> Params) {
1402 OS << '['
1403 << join(map_range(Params,
1404 [](auto &O) {
1405 return (O.Name + ":" + getParamKindStr(O.Kind)).str();
1407 ", ")
1408 << ']';
1411 //===- PatFragPattern -----------------------------------------------------===//
1413 class PatFragPattern : public InstructionPattern {
1414 public:
1415 PatFragPattern(const PatFrag &PF, StringRef Name)
1416 : InstructionPattern(K_PatFrag, Name), PF(PF) {}
1418 static bool classof(const Pattern *P) { return P->getKind() == K_PatFrag; }
1420 const PatFrag &getPatFrag() const { return PF; }
1421 StringRef getInstName() const override { return PF.getName(); }
1423 unsigned getNumInstDefs() const override { return PF.num_out_params(); }
1424 unsigned getNumInstOperands() const override { return PF.num_params(); }
1426 ArrayRef<InstructionOperand> getApplyDefsNeeded() const override;
1428 bool checkSemantics(ArrayRef<SMLoc> DiagLoc) override;
1430 /// Before emitting the patterns inside the PatFrag, add all necessary code
1431 /// expansions to \p PatFragCEs imported from \p ParentCEs.
1433 /// For a MachineOperand PatFrag parameter, this will fetch the expansion for
1434 /// that operand from \p ParentCEs and add it to \p PatFragCEs. Errors can be
1435 /// emitted if the MachineOperand reference is unbound.
1437 /// For an Immediate PatFrag parameter this simply adds the integer value to
1438 /// \p PatFragCEs as an expansion.
1440 /// \param ParentCEs Contains all of the code expansions declared by the other
1441 /// patterns emitted so far in the pattern list containing
1442 /// this PatFragPattern.
1443 /// \param PatFragCEs Output Code Expansions (usually empty)
1444 /// \param DiagLoc Diagnostic loc in case an error occurs.
1445 /// \return `true` on success, `false` on failure.
1446 bool mapInputCodeExpansions(const CodeExpansions &ParentCEs,
1447 CodeExpansions &PatFragCEs,
1448 ArrayRef<SMLoc> DiagLoc) const;
1450 private:
1451 const PatFrag &PF;
1454 ArrayRef<InstructionOperand> PatFragPattern::getApplyDefsNeeded() const {
1455 assert(PF.num_roots() == 1);
1456 // Only roots need to be redef.
1457 for (auto [Idx, Param] : enumerate(PF.out_params())) {
1458 if (Param.Kind == PatFrag::PK_Root)
1459 return getOperand(Idx);
1461 llvm_unreachable("root not found!");
1464 bool PatFragPattern::checkSemantics(ArrayRef<SMLoc> DiagLoc) {
1465 if (!InstructionPattern::checkSemantics(DiagLoc))
1466 return false;
1468 for (const auto &[Idx, Op] : enumerate(Operands)) {
1469 switch (PF.getParam(Idx).Kind) {
1470 case PatFrag::PK_Imm:
1471 if (!Op.hasImmValue()) {
1472 PrintError(DiagLoc, "expected operand " + to_string(Idx) + " of '" +
1473 getInstName() + "' to be an immediate; got " +
1474 Op.describe());
1475 return false;
1477 if (Op.isNamedImmediate()) {
1478 PrintError(DiagLoc, "operand " + to_string(Idx) + " of '" +
1479 getInstName() +
1480 "' cannot be a named immediate");
1481 return false;
1483 break;
1484 case PatFrag::PK_Root:
1485 case PatFrag::PK_MachineOperand:
1486 if (!Op.isNamedOperand() || Op.isNamedImmediate()) {
1487 PrintError(DiagLoc, "expected operand " + to_string(Idx) + " of '" +
1488 getInstName() +
1489 "' to be a MachineOperand; got " +
1490 Op.describe());
1491 return false;
1493 break;
1497 return true;
1500 bool PatFragPattern::mapInputCodeExpansions(const CodeExpansions &ParentCEs,
1501 CodeExpansions &PatFragCEs,
1502 ArrayRef<SMLoc> DiagLoc) const {
1503 for (const auto &[Idx, Op] : enumerate(operands())) {
1504 StringRef ParamName = PF.getParam(Idx).Name;
1506 // Operands to a PFP can only be named, or be an immediate, but not a named
1507 // immediate.
1508 assert(!Op.isNamedImmediate());
1510 if (Op.isNamedOperand()) {
1511 StringRef ArgName = Op.getOperandName();
1512 // Map it only if it's been defined.
1513 auto It = ParentCEs.find(ArgName);
1514 if (It == ParentCEs.end()) {
1515 if (!PF.handleUnboundInParam(ParamName, ArgName, DiagLoc))
1516 return false;
1517 } else
1518 PatFragCEs.declare(ParamName, It->second);
1519 continue;
1522 if (Op.hasImmValue()) {
1523 PatFragCEs.declare(ParamName, to_string(Op.getImmValue()));
1524 continue;
1527 llvm_unreachable("Unknown Operand Type!");
1530 return true;
1533 //===- BuiltinPattern -----------------------------------------------------===//
1535 enum BuiltinKind {
1536 BI_ReplaceReg,
1537 BI_EraseRoot,
1540 class BuiltinPattern : public InstructionPattern {
1541 struct BuiltinInfo {
1542 StringLiteral DefName;
1543 BuiltinKind Kind;
1544 unsigned NumOps;
1545 unsigned NumDefs;
1548 static constexpr std::array<BuiltinInfo, 2> KnownBuiltins = {{
1549 {"GIReplaceReg", BI_ReplaceReg, 2, 1},
1550 {"GIEraseRoot", BI_EraseRoot, 0, 0},
1553 public:
1554 BuiltinPattern(const Record &Def, StringRef Name)
1555 : InstructionPattern(K_Builtin, Name), I(getBuiltinInfo(Def)) {}
1557 static bool classof(const Pattern *P) { return P->getKind() == K_Builtin; }
1559 unsigned getNumInstOperands() const override { return I.NumOps; }
1560 unsigned getNumInstDefs() const override { return I.NumDefs; }
1561 StringRef getInstName() const override { return I.DefName; }
1562 BuiltinKind getBuiltinKind() const { return I.Kind; }
1564 bool checkSemantics(ArrayRef<SMLoc> Loc) override;
1566 private:
1567 static BuiltinInfo getBuiltinInfo(const Record &Def);
1569 BuiltinInfo I;
1572 BuiltinPattern::BuiltinInfo BuiltinPattern::getBuiltinInfo(const Record &Def) {
1573 assert(Def.isSubClassOf(BuiltinInstClassName));
1575 StringRef Name = Def.getName();
1576 for (const auto &KBI : KnownBuiltins) {
1577 if (KBI.DefName == Name)
1578 return KBI;
1581 PrintFatalError(Def.getLoc(), "Unimplemented " + BuiltinInstClassName +
1582 " def '" + Name + "'");
1585 bool BuiltinPattern::checkSemantics(ArrayRef<SMLoc> Loc) {
1586 if (!InstructionPattern::checkSemantics(Loc))
1587 return false;
1589 // For now all builtins just take names, no immediates.
1590 for (const auto &[Idx, Op] : enumerate(operands())) {
1591 if (!Op.isNamedOperand() || Op.isNamedImmediate()) {
1592 PrintError(Loc, "expected operand " + to_string(Idx) + " of '" +
1593 getInstName() + "' to be a name");
1594 return false;
1598 return true;
1601 //===- PrettyStackTrace Helpers ------------------------------------------===//
1603 class PrettyStackTraceParse : public PrettyStackTraceEntry {
1604 const Record &Def;
1606 public:
1607 PrettyStackTraceParse(const Record &Def) : Def(Def) {}
1609 void print(raw_ostream &OS) const override {
1610 if (Def.isSubClassOf("GICombineRule"))
1611 OS << "Parsing GICombineRule '" << Def.getName() << "'";
1612 else if (Def.isSubClassOf(PatFragClassName))
1613 OS << "Parsing " << PatFragClassName << " '" << Def.getName() << "'";
1614 else
1615 OS << "Parsing '" << Def.getName() << "'";
1616 OS << "\n";
1620 class PrettyStackTraceEmit : public PrettyStackTraceEntry {
1621 const Record &Def;
1622 const Pattern *Pat = nullptr;
1624 public:
1625 PrettyStackTraceEmit(const Record &Def, const Pattern *Pat = nullptr)
1626 : Def(Def), Pat(Pat) {}
1628 void print(raw_ostream &OS) const override {
1629 if (Def.isSubClassOf("GICombineRule"))
1630 OS << "Emitting GICombineRule '" << Def.getName() << "'";
1631 else if (Def.isSubClassOf(PatFragClassName))
1632 OS << "Emitting " << PatFragClassName << " '" << Def.getName() << "'";
1633 else
1634 OS << "Emitting '" << Def.getName() << "'";
1636 if (Pat)
1637 OS << " [" << Pat->getKindName() << " '" << Pat->getName() << "']";
1638 OS << "\n";
1642 //===- CombineRuleBuilder -------------------------------------------------===//
1644 /// Parses combine rule and builds a small intermediate representation to tie
1645 /// patterns together and emit RuleMatchers to match them. This may emit more
1646 /// than one RuleMatcher, e.g. for `wip_match_opcode`.
1648 /// Memory management for `Pattern` objects is done through `std::unique_ptr`.
1649 /// In most cases, there are two stages to a pattern's lifetime:
1650 /// - Creation in a `parse` function
1651 /// - The unique_ptr is stored in a variable, and may be destroyed if the
1652 /// pattern is found to be semantically invalid.
1653 /// - Ownership transfer into a `PatternMap`
1654 /// - Once a pattern is moved into either the map of Match or Apply
1655 /// patterns, it is known to be valid and it never moves back.
1656 class CombineRuleBuilder {
1657 public:
1658 using PatternMap = MapVector<StringRef, std::unique_ptr<Pattern>>;
1659 using PatternAlternatives = DenseMap<const Pattern *, unsigned>;
1661 CombineRuleBuilder(const CodeGenTarget &CGT,
1662 SubtargetFeatureInfoMap &SubtargetFeatures,
1663 Record &RuleDef, unsigned ID,
1664 std::vector<RuleMatcher> &OutRMs)
1665 : CGT(CGT), SubtargetFeatures(SubtargetFeatures), RuleDef(RuleDef),
1666 RuleID(ID), OutRMs(OutRMs) {}
1668 /// Parses all fields in the RuleDef record.
1669 bool parseAll();
1671 /// Emits all RuleMatchers into the vector of RuleMatchers passed in the
1672 /// constructor.
1673 bool emitRuleMatchers();
1675 void print(raw_ostream &OS) const;
1676 void dump() const { print(dbgs()); }
1678 /// Debug-only verification of invariants.
1679 #ifndef NDEBUG
1680 void verify() const;
1681 #endif
1683 private:
1684 const CodeGenInstruction &getGConstant() const {
1685 return CGT.getInstruction(RuleDef.getRecords().getDef("G_CONSTANT"));
1688 void PrintError(Twine Msg) const { ::PrintError(&RuleDef, Msg); }
1689 void PrintWarning(Twine Msg) const { ::PrintWarning(RuleDef.getLoc(), Msg); }
1690 void PrintNote(Twine Msg) const { ::PrintNote(RuleDef.getLoc(), Msg); }
1692 void print(raw_ostream &OS, const PatternAlternatives &Alts) const;
1694 bool addApplyPattern(std::unique_ptr<Pattern> Pat);
1695 bool addMatchPattern(std::unique_ptr<Pattern> Pat);
1697 /// Adds the expansions from \see MatchDatas to \p CE.
1698 void declareAllMatchDatasExpansions(CodeExpansions &CE) const;
1700 /// Adds a matcher \p P to \p IM, expanding its code using \p CE.
1701 /// Note that the predicate is added on the last InstructionMatcher.
1703 /// \p Alts is only used if DebugCXXPreds is enabled.
1704 void addCXXPredicate(RuleMatcher &M, const CodeExpansions &CE,
1705 const CXXPattern &P, const PatternAlternatives &Alts);
1707 /// Adds an apply \p P to \p IM, expanding its code using \p CE.
1708 void addCXXAction(RuleMatcher &M, const CodeExpansions &CE,
1709 const CXXPattern &P);
1711 bool hasOnlyCXXApplyPatterns() const;
1712 bool hasEraseRoot() const;
1714 // Infer machine operand types and check their consistency.
1715 bool typecheckPatterns();
1717 /// For all PatFragPatterns, add a new entry in PatternAlternatives for each
1718 /// PatternList it contains. This is multiplicative, so if we have 2
1719 /// PatFrags with 3 alternatives each, we get 2*3 permutations added to
1720 /// PermutationsToEmit. The "MaxPermutations" field controls how many
1721 /// permutations are allowed before an error is emitted and this function
1722 /// returns false. This is a simple safeguard to prevent combination of
1723 /// PatFrags from generating enormous amounts of rules.
1724 bool buildPermutationsToEmit();
1726 /// Checks additional semantics of the Patterns.
1727 bool checkSemantics();
1729 /// Creates a new RuleMatcher with some boilerplate
1730 /// settings/actions/predicates, and and adds it to \p OutRMs.
1731 /// \see addFeaturePredicates too.
1733 /// \param Alts Current set of alternatives, for debug comment.
1734 /// \param AdditionalComment Comment string to be added to the
1735 /// `DebugCommentAction`.
1736 RuleMatcher &addRuleMatcher(const PatternAlternatives &Alts,
1737 Twine AdditionalComment = "");
1738 bool addFeaturePredicates(RuleMatcher &M);
1740 bool findRoots();
1741 bool buildRuleOperandsTable();
1743 bool parseDefs(const DagInit &Def);
1744 bool
1745 parsePatternList(const DagInit &List,
1746 function_ref<bool(std::unique_ptr<Pattern>)> ParseAction,
1747 StringRef Operator, ArrayRef<SMLoc> DiagLoc,
1748 StringRef AnonPatNamePrefix) const;
1750 std::unique_ptr<Pattern> parseInstructionPattern(const Init &Arg,
1751 StringRef PatName) const;
1752 std::unique_ptr<Pattern> parseWipMatchOpcodeMatcher(const Init &Arg,
1753 StringRef PatName) const;
1754 bool parseInstructionPatternOperand(InstructionPattern &IP,
1755 const Init *OpInit,
1756 const StringInit *OpName) const;
1757 std::unique_ptr<PatFrag> parsePatFragImpl(const Record *Def) const;
1758 bool parsePatFragParamList(
1759 ArrayRef<SMLoc> DiagLoc, const DagInit &OpsList,
1760 function_ref<bool(StringRef, PatFrag::ParamKind)> ParseAction) const;
1761 const PatFrag *parsePatFrag(const Record *Def) const;
1763 bool emitMatchPattern(CodeExpansions &CE, const PatternAlternatives &Alts,
1764 const InstructionPattern &IP);
1765 bool emitMatchPattern(CodeExpansions &CE, const PatternAlternatives &Alts,
1766 const AnyOpcodePattern &AOP);
1768 bool emitPatFragMatchPattern(CodeExpansions &CE,
1769 const PatternAlternatives &Alts, RuleMatcher &RM,
1770 InstructionMatcher *IM,
1771 const PatFragPattern &PFP,
1772 DenseSet<const Pattern *> &SeenPats);
1774 bool emitApplyPatterns(CodeExpansions &CE, RuleMatcher &M);
1776 // Recursively visits InstructionPatterns from P to build up the
1777 // RuleMatcher actions.
1778 bool emitInstructionApplyPattern(CodeExpansions &CE, RuleMatcher &M,
1779 const InstructionPattern &P,
1780 DenseSet<const Pattern *> &SeenPats,
1781 StringMap<unsigned> &OperandToTempRegID);
1783 bool emitCodeGenInstructionApplyImmOperand(RuleMatcher &M,
1784 BuildMIAction &DstMI,
1785 const CodeGenInstructionPattern &P,
1786 const InstructionOperand &O);
1788 bool emitBuiltinApplyPattern(CodeExpansions &CE, RuleMatcher &M,
1789 const BuiltinPattern &P,
1790 StringMap<unsigned> &OperandToTempRegID);
1792 // Recursively visits CodeGenInstructionPattern from P to build up the
1793 // RuleMatcher/InstructionMatcher. May create new InstructionMatchers as
1794 // needed.
1795 using OperandMapperFnRef =
1796 function_ref<InstructionOperand(const InstructionOperand &)>;
1797 using OperandDefLookupFn =
1798 function_ref<const InstructionPattern *(StringRef)>;
1799 bool emitCodeGenInstructionMatchPattern(
1800 CodeExpansions &CE, const PatternAlternatives &Alts, RuleMatcher &M,
1801 InstructionMatcher &IM, const CodeGenInstructionPattern &P,
1802 DenseSet<const Pattern *> &SeenPats, OperandDefLookupFn LookupOperandDef,
1803 OperandMapperFnRef OperandMapper = [](const auto &O) { return O; });
1805 const CodeGenTarget &CGT;
1806 SubtargetFeatureInfoMap &SubtargetFeatures;
1807 Record &RuleDef;
1808 const unsigned RuleID;
1809 std::vector<RuleMatcher> &OutRMs;
1811 // For InstructionMatcher::addOperand
1812 unsigned AllocatedTemporariesBaseID = 0;
1814 /// The root of the pattern.
1815 StringRef RootName;
1817 /// These maps have ownership of the actual Pattern objects.
1818 /// They both map a Pattern's name to the Pattern instance.
1819 PatternMap MatchPats;
1820 PatternMap ApplyPats;
1822 /// Operand tables to tie match/apply patterns together.
1823 OperandTable<> MatchOpTable;
1824 OperandTable<> ApplyOpTable;
1826 /// Set by findRoots.
1827 Pattern *MatchRoot = nullptr;
1828 SmallDenseSet<InstructionPattern *, 2> ApplyRoots;
1830 SmallVector<MatchDataInfo, 2> MatchDatas;
1831 SmallVector<PatternAlternatives, 1> PermutationsToEmit;
1833 // print()/debug-only members.
1834 mutable SmallPtrSet<const PatFrag *, 2> SeenPatFrags;
1837 bool CombineRuleBuilder::parseAll() {
1838 auto StackTrace = PrettyStackTraceParse(RuleDef);
1840 if (!parseDefs(*RuleDef.getValueAsDag("Defs")))
1841 return false;
1843 if (!parsePatternList(
1844 *RuleDef.getValueAsDag("Match"),
1845 [this](auto Pat) { return addMatchPattern(std::move(Pat)); }, "match",
1846 RuleDef.getLoc(), (RuleDef.getName() + "_match").str()))
1847 return false;
1849 if (!parsePatternList(
1850 *RuleDef.getValueAsDag("Apply"),
1851 [this](auto Pat) { return addApplyPattern(std::move(Pat)); }, "apply",
1852 RuleDef.getLoc(), (RuleDef.getName() + "_apply").str()))
1853 return false;
1855 if (!buildRuleOperandsTable() || !typecheckPatterns() || !findRoots() ||
1856 !checkSemantics() || !buildPermutationsToEmit())
1857 return false;
1858 LLVM_DEBUG(verify());
1859 return true;
1862 bool CombineRuleBuilder::emitRuleMatchers() {
1863 auto StackTrace = PrettyStackTraceEmit(RuleDef);
1865 assert(MatchRoot);
1866 CodeExpansions CE;
1867 declareAllMatchDatasExpansions(CE);
1869 assert(!PermutationsToEmit.empty());
1870 for (const auto &Alts : PermutationsToEmit) {
1871 switch (MatchRoot->getKind()) {
1872 case Pattern::K_AnyOpcode: {
1873 if (!emitMatchPattern(CE, Alts, *cast<AnyOpcodePattern>(MatchRoot)))
1874 return false;
1875 break;
1877 case Pattern::K_PatFrag:
1878 case Pattern::K_Builtin:
1879 case Pattern::K_CodeGenInstruction:
1880 if (!emitMatchPattern(CE, Alts, *cast<InstructionPattern>(MatchRoot)))
1881 return false;
1882 break;
1883 case Pattern::K_CXX:
1884 PrintError("C++ code cannot be the root of a rule!");
1885 return false;
1886 default:
1887 llvm_unreachable("unknown pattern kind!");
1891 return true;
1894 void CombineRuleBuilder::print(raw_ostream &OS) const {
1895 OS << "(CombineRule name:" << RuleDef.getName() << " id:" << RuleID
1896 << " root:" << RootName << "\n";
1898 if (!MatchDatas.empty()) {
1899 OS << " (MatchDatas\n";
1900 for (const auto &MD : MatchDatas) {
1901 OS << " ";
1902 MD.print(OS);
1903 OS << "\n";
1905 OS << " )\n";
1908 if (!SeenPatFrags.empty()) {
1909 OS << " (PatFrags\n";
1910 for (const auto *PF : SeenPatFrags) {
1911 PF->print(OS, /*Indent=*/" ");
1912 OS << "\n";
1914 OS << " )\n";
1917 const auto DumpPats = [&](StringRef Name, const PatternMap &Pats) {
1918 OS << " (" << Name << " ";
1919 if (Pats.empty()) {
1920 OS << "<empty>)\n";
1921 return;
1924 OS << "\n";
1925 for (const auto &[Name, Pat] : Pats) {
1926 OS << " ";
1927 if (Pat.get() == MatchRoot)
1928 OS << "<match_root>";
1929 if (isa<InstructionPattern>(Pat.get()) &&
1930 ApplyRoots.contains(cast<InstructionPattern>(Pat.get())))
1931 OS << "<apply_root>";
1932 OS << Name << ":";
1933 Pat->print(OS, /*PrintName=*/false);
1934 OS << "\n";
1936 OS << " )\n";
1939 DumpPats("MatchPats", MatchPats);
1940 DumpPats("ApplyPats", ApplyPats);
1942 MatchOpTable.print(OS, "MatchPats", /*Indent*/ " ");
1943 ApplyOpTable.print(OS, "ApplyPats", /*Indent*/ " ");
1945 if (PermutationsToEmit.size() > 1) {
1946 OS << " (PermutationsToEmit\n";
1947 for (const auto &Perm : PermutationsToEmit) {
1948 OS << " ";
1949 print(OS, Perm);
1950 OS << ",\n";
1952 OS << " )\n";
1955 OS << ")\n";
1958 #ifndef NDEBUG
1959 void CombineRuleBuilder::verify() const {
1960 const auto VerifyPats = [&](const PatternMap &Pats) {
1961 for (const auto &[Name, Pat] : Pats) {
1962 if (!Pat)
1963 PrintFatalError("null pattern in pattern map!");
1965 if (Name != Pat->getName()) {
1966 Pat->dump();
1967 PrintFatalError("Pattern name mismatch! Map name: " + Name +
1968 ", Pat name: " + Pat->getName());
1971 // Sanity check: the map should point to the same data as the Pattern.
1972 // Both strings are allocated in the pool using insertStrRef.
1973 if (Name.data() != Pat->getName().data()) {
1974 dbgs() << "Map StringRef: '" << Name << "' @ "
1975 << (const void *)Name.data() << "\n";
1976 dbgs() << "Pat String: '" << Pat->getName() << "' @ "
1977 << (const void *)Pat->getName().data() << "\n";
1978 PrintFatalError("StringRef stored in the PatternMap is not referencing "
1979 "the same string as its Pattern!");
1984 VerifyPats(MatchPats);
1985 VerifyPats(ApplyPats);
1987 // Check there are no wip_match_opcode patterns in the "apply" patterns.
1988 if (any_of(ApplyPats,
1989 [&](auto &E) { return isa<AnyOpcodePattern>(E.second.get()); })) {
1990 dump();
1991 PrintFatalError(
1992 "illegal wip_match_opcode pattern in the 'apply' patterns!");
1995 // Check there are no nullptrs in ApplyRoots.
1996 if (ApplyRoots.contains(nullptr)) {
1997 PrintFatalError(
1998 "CombineRuleBuilder's ApplyRoots set contains a null pointer!");
2001 #endif
2003 void CombineRuleBuilder::print(raw_ostream &OS,
2004 const PatternAlternatives &Alts) const {
2005 SmallVector<std::string, 1> Strings(
2006 map_range(Alts, [](const auto &PatAndPerm) {
2007 return PatAndPerm.first->getName().str() + "[" +
2008 to_string(PatAndPerm.second) + "]";
2009 }));
2010 // Sort so output is deterministic for tests. Otherwise it's sorted by pointer
2011 // values.
2012 sort(Strings);
2013 OS << "[" << join(Strings, ", ") << "]";
2016 bool CombineRuleBuilder::addApplyPattern(std::unique_ptr<Pattern> Pat) {
2017 StringRef Name = Pat->getName();
2018 if (ApplyPats.contains(Name)) {
2019 PrintError("'" + Name + "' apply pattern defined more than once!");
2020 return false;
2023 if (isa<AnyOpcodePattern>(Pat.get())) {
2024 PrintError("'" + Name +
2025 "': wip_match_opcode is not supported in apply patterns");
2026 return false;
2029 if (isa<PatFragPattern>(Pat.get())) {
2030 PrintError("'" + Name + "': using " + PatFragClassName +
2031 " is not supported in apply patterns");
2032 return false;
2035 if (auto *CXXPat = dyn_cast<CXXPattern>(Pat.get()))
2036 CXXPat->setIsApply();
2038 ApplyPats[Name] = std::move(Pat);
2039 return true;
2042 bool CombineRuleBuilder::addMatchPattern(std::unique_ptr<Pattern> Pat) {
2043 StringRef Name = Pat->getName();
2044 if (MatchPats.contains(Name)) {
2045 PrintError("'" + Name + "' match pattern defined more than once!");
2046 return false;
2049 // For now, none of the builtins can appear in 'match'.
2050 if (const auto *BP = dyn_cast<BuiltinPattern>(Pat.get())) {
2051 PrintError("'" + BP->getInstName() +
2052 "' cannot be used in a 'match' pattern");
2053 return false;
2056 MatchPats[Name] = std::move(Pat);
2057 return true;
2060 void CombineRuleBuilder::declareAllMatchDatasExpansions(
2061 CodeExpansions &CE) const {
2062 for (const auto &MD : MatchDatas)
2063 CE.declare(MD.getPatternSymbol(), MD.getQualifiedVariableName());
2066 void CombineRuleBuilder::addCXXPredicate(RuleMatcher &M,
2067 const CodeExpansions &CE,
2068 const CXXPattern &P,
2069 const PatternAlternatives &Alts) {
2070 // FIXME: Hack so C++ code is executed last. May not work for more complex
2071 // patterns.
2072 auto &IM = *std::prev(M.insnmatchers().end());
2073 const auto &ExpandedCode =
2074 P.expandCode(CE, RuleDef.getLoc(), [&](raw_ostream &OS) {
2075 OS << "// Pattern Alternatives: ";
2076 print(OS, Alts);
2077 OS << "\n";
2079 IM->addPredicate<GenericInstructionPredicateMatcher>(
2080 ExpandedCode.getEnumNameWithPrefix(CXXPredPrefix));
2083 void CombineRuleBuilder::addCXXAction(RuleMatcher &M, const CodeExpansions &CE,
2084 const CXXPattern &P) {
2085 const auto &ExpandedCode = P.expandCode(CE, RuleDef.getLoc());
2086 M.addAction<CustomCXXAction>(
2087 ExpandedCode.getEnumNameWithPrefix(CXXApplyPrefix));
2090 bool CombineRuleBuilder::hasOnlyCXXApplyPatterns() const {
2091 return all_of(ApplyPats, [&](auto &Entry) {
2092 return isa<CXXPattern>(Entry.second.get());
2096 bool CombineRuleBuilder::hasEraseRoot() const {
2097 return any_of(ApplyPats, [&](auto &Entry) {
2098 if (const auto *BP = dyn_cast<BuiltinPattern>(Entry.second.get()))
2099 return BP->getBuiltinKind() == BI_EraseRoot;
2100 return false;
2104 bool CombineRuleBuilder::typecheckPatterns() {
2105 OperandTypeChecker OTC(RuleDef.getLoc());
2107 const auto CheckMatchTypeOf = [&](const PatternType &) -> bool {
2108 // We'll reject those after we're done inferring
2109 return true;
2112 for (auto &Pat : values(MatchPats)) {
2113 if (auto *IP = dyn_cast<InstructionPattern>(Pat.get())) {
2114 if (!OTC.check(IP, CheckMatchTypeOf))
2115 return false;
2119 const auto CheckApplyTypeOf = [&](const PatternType &Ty) {
2120 // GITypeOf<"$x"> can only be used if "$x" is a matched operand.
2121 const auto OpName = Ty.getTypeOfOpName();
2122 if (MatchOpTable.lookup(OpName).Found)
2123 return true;
2125 PrintError("'" + OpName + "' ('" + Ty.str() +
2126 "') does not refer to a matched operand!");
2127 return false;
2130 for (auto &Pat : values(ApplyPats)) {
2131 if (auto *IP = dyn_cast<InstructionPattern>(Pat.get())) {
2132 if (!OTC.check(IP, CheckApplyTypeOf))
2133 return false;
2137 OTC.setAllOperandTypes();
2139 // Always check this after in case inference adds some special types to the
2140 // match patterns.
2141 for (auto &Pat : values(MatchPats)) {
2142 if (auto *IP = dyn_cast<InstructionPattern>(Pat.get())) {
2143 if (IP->diagnoseAllSpecialTypes(
2144 RuleDef.getLoc(),
2145 SpecialTyClassName + " is not supported in 'match' patterns")) {
2146 return false;
2150 return true;
2153 bool CombineRuleBuilder::buildPermutationsToEmit() {
2154 PermutationsToEmit.clear();
2156 // Start with one empty set of alternatives.
2157 PermutationsToEmit.emplace_back();
2158 for (const auto &Pat : values(MatchPats)) {
2159 unsigned NumAlts = 0;
2160 // Note: technically, AnyOpcodePattern also needs permutations, but:
2161 // - We only allow a single one of them in the root.
2162 // - They cannot be mixed with any other pattern other than C++ code.
2163 // So we don't really need to take them into account here. We could, but
2164 // that pattern is a hack anyway and the less it's involved, the better.
2165 if (const auto *PFP = dyn_cast<PatFragPattern>(Pat.get()))
2166 NumAlts = PFP->getPatFrag().num_alternatives();
2167 else
2168 continue;
2170 // For each pattern that needs permutations, multiply the current set of
2171 // alternatives.
2172 auto CurPerms = PermutationsToEmit;
2173 PermutationsToEmit.clear();
2175 for (const auto &Perm : CurPerms) {
2176 assert(!Perm.count(Pat.get()) && "Pattern already emitted?");
2177 for (unsigned K = 0; K < NumAlts; ++K) {
2178 PatternAlternatives NewPerm = Perm;
2179 NewPerm[Pat.get()] = K;
2180 PermutationsToEmit.emplace_back(std::move(NewPerm));
2185 if (int64_t MaxPerms = RuleDef.getValueAsInt("MaxPermutations");
2186 MaxPerms > 0) {
2187 if ((int64_t)PermutationsToEmit.size() > MaxPerms) {
2188 PrintError("cannot emit rule '" + RuleDef.getName() + "'; " +
2189 Twine(PermutationsToEmit.size()) +
2190 " permutations would be emitted, but the max is " +
2191 Twine(MaxPerms));
2192 return false;
2196 // Ensure we always have a single empty entry, it simplifies the emission
2197 // logic so it doesn't need to handle the case where there are no perms.
2198 if (PermutationsToEmit.empty()) {
2199 PermutationsToEmit.emplace_back();
2200 return true;
2203 return true;
2206 bool CombineRuleBuilder::checkSemantics() {
2207 assert(MatchRoot && "Cannot call this before findRoots()");
2209 bool UsesWipMatchOpcode = false;
2210 for (const auto &Match : MatchPats) {
2211 const auto *Pat = Match.second.get();
2213 if (const auto *CXXPat = dyn_cast<CXXPattern>(Pat)) {
2214 if (!CXXPat->getRawCode().contains("return "))
2215 PrintWarning("'match' C++ code does not seem to return!");
2216 continue;
2219 const auto *AOP = dyn_cast<AnyOpcodePattern>(Pat);
2220 if (!AOP)
2221 continue;
2223 if (UsesWipMatchOpcode) {
2224 PrintError("wip_opcode_match can only be present once");
2225 return false;
2228 UsesWipMatchOpcode = true;
2231 for (const auto &Apply : ApplyPats) {
2232 assert(Apply.second.get());
2233 const auto *IP = dyn_cast<InstructionPattern>(Apply.second.get());
2234 if (!IP)
2235 continue;
2237 if (UsesWipMatchOpcode) {
2238 PrintError("cannot use wip_match_opcode in combination with apply "
2239 "instruction patterns!");
2240 return false;
2243 const auto *BIP = dyn_cast<BuiltinPattern>(IP);
2244 if (!BIP)
2245 continue;
2246 StringRef Name = BIP->getInstName();
2248 // (GIEraseInst) has to be the only apply pattern, or it can not be used at
2249 // all. The root cannot have any defs either.
2250 switch (BIP->getBuiltinKind()) {
2251 case BI_EraseRoot: {
2252 if (ApplyPats.size() > 1) {
2253 PrintError(Name + " must be the only 'apply' pattern");
2254 return false;
2257 const auto *IRoot = dyn_cast<CodeGenInstructionPattern>(MatchRoot);
2258 if (!IRoot) {
2259 PrintError(Name +
2260 " can only be used if the root is a CodeGenInstruction");
2261 return false;
2264 if (IRoot->getNumInstDefs() != 0) {
2265 PrintError(Name + " can only be used if on roots that do "
2266 "not have any output operand");
2267 PrintNote("'" + IRoot->getInstName() + "' has " +
2268 Twine(IRoot->getNumInstDefs()) + " output operands");
2269 return false;
2271 break;
2273 case BI_ReplaceReg: {
2274 // (GIReplaceReg can only be used on the root instruction)
2275 // TODO: When we allow rewriting non-root instructions, also allow this.
2276 StringRef OldRegName = BIP->getOperand(0).getOperandName();
2277 auto *Def = MatchOpTable.getDef(OldRegName);
2278 if (!Def) {
2279 PrintError(Name + " cannot find a matched pattern that defines '" +
2280 OldRegName + "'");
2281 return false;
2283 if (MatchOpTable.getDef(OldRegName) != MatchRoot) {
2284 PrintError(Name + " cannot replace '" + OldRegName +
2285 "': this builtin can only replace a register defined by the "
2286 "match root");
2287 return false;
2289 break;
2294 return true;
2297 RuleMatcher &CombineRuleBuilder::addRuleMatcher(const PatternAlternatives &Alts,
2298 Twine AdditionalComment) {
2299 auto &RM = OutRMs.emplace_back(RuleDef.getLoc());
2300 addFeaturePredicates(RM);
2301 RM.setPermanentGISelFlags(GISF_IgnoreCopies);
2302 RM.addRequiredSimplePredicate(getIsEnabledPredicateEnumName(RuleID));
2304 std::string Comment;
2305 raw_string_ostream CommentOS(Comment);
2306 CommentOS << "Combiner Rule #" << RuleID << ": " << RuleDef.getName();
2307 if (!Alts.empty()) {
2308 CommentOS << " @ ";
2309 print(CommentOS, Alts);
2311 if (!AdditionalComment.isTriviallyEmpty())
2312 CommentOS << "; " << AdditionalComment;
2313 RM.addAction<DebugCommentAction>(Comment);
2314 return RM;
2317 bool CombineRuleBuilder::addFeaturePredicates(RuleMatcher &M) {
2318 if (!RuleDef.getValue("Predicates"))
2319 return true;
2321 ListInit *Preds = RuleDef.getValueAsListInit("Predicates");
2322 for (Init *PI : Preds->getValues()) {
2323 DefInit *Pred = dyn_cast<DefInit>(PI);
2324 if (!Pred)
2325 continue;
2327 Record *Def = Pred->getDef();
2328 if (!Def->isSubClassOf("Predicate")) {
2329 ::PrintError(Def, "Unknown 'Predicate' Type");
2330 return false;
2333 if (Def->getValueAsString("CondString").empty())
2334 continue;
2336 if (SubtargetFeatures.count(Def) == 0) {
2337 SubtargetFeatures.emplace(
2338 Def, SubtargetFeatureInfo(Def, SubtargetFeatures.size()));
2341 M.addRequiredFeature(Def);
2344 return true;
2347 bool CombineRuleBuilder::findRoots() {
2348 const auto Finish = [&]() {
2349 assert(MatchRoot);
2351 if (hasOnlyCXXApplyPatterns() || hasEraseRoot())
2352 return true;
2354 auto *IPRoot = dyn_cast<InstructionPattern>(MatchRoot);
2355 if (!IPRoot)
2356 return true;
2358 if (IPRoot->getNumInstDefs() == 0) {
2359 // No defs to work with -> find the root using the pattern name.
2360 auto It = ApplyPats.find(RootName);
2361 if (It == ApplyPats.end()) {
2362 PrintError("Cannot find root '" + RootName + "' in apply patterns!");
2363 return false;
2366 auto *ApplyRoot = dyn_cast<InstructionPattern>(It->second.get());
2367 if (!ApplyRoot) {
2368 PrintError("apply pattern root '" + RootName +
2369 "' must be an instruction pattern");
2370 return false;
2373 ApplyRoots.insert(ApplyRoot);
2374 return true;
2377 // Collect all redefinitions of the MatchRoot's defs and put them in
2378 // ApplyRoots.
2379 const auto DefsNeeded = IPRoot->getApplyDefsNeeded();
2380 for (auto &Op : DefsNeeded) {
2381 assert(Op.isDef() && Op.isNamedOperand());
2382 StringRef Name = Op.getOperandName();
2384 auto *ApplyRedef = ApplyOpTable.getDef(Name);
2385 if (!ApplyRedef) {
2386 PrintError("'" + Name + "' must be redefined in the 'apply' pattern");
2387 return false;
2390 ApplyRoots.insert((InstructionPattern *)ApplyRedef);
2393 if (auto It = ApplyPats.find(RootName); It != ApplyPats.end()) {
2394 if (find(ApplyRoots, It->second.get()) == ApplyRoots.end()) {
2395 PrintError("apply pattern '" + RootName +
2396 "' is supposed to be a root but it does not redefine any of "
2397 "the defs of the match root");
2398 return false;
2402 return true;
2405 // Look by pattern name, e.g.
2406 // (G_FNEG $x, $y):$root
2407 if (auto MatchPatIt = MatchPats.find(RootName);
2408 MatchPatIt != MatchPats.end()) {
2409 MatchRoot = MatchPatIt->second.get();
2410 return Finish();
2413 // Look by def:
2414 // (G_FNEG $root, $y)
2415 auto LookupRes = MatchOpTable.lookup(RootName);
2416 if (!LookupRes.Found) {
2417 PrintError("Cannot find root '" + RootName + "' in match patterns!");
2418 return false;
2421 MatchRoot = LookupRes.Def;
2422 if (!MatchRoot) {
2423 PrintError("Cannot use live-in operand '" + RootName +
2424 "' as match pattern root!");
2425 return false;
2428 return Finish();
2431 bool CombineRuleBuilder::buildRuleOperandsTable() {
2432 const auto DiagnoseRedefMatch = [&](StringRef OpName) {
2433 PrintError("Operand '" + OpName +
2434 "' is defined multiple times in the 'match' patterns");
2437 const auto DiagnoseRedefApply = [&](StringRef OpName) {
2438 PrintError("Operand '" + OpName +
2439 "' is defined multiple times in the 'apply' patterns");
2442 for (auto &Pat : values(MatchPats)) {
2443 auto *IP = dyn_cast<InstructionPattern>(Pat.get());
2444 if (IP && !MatchOpTable.addPattern(IP, DiagnoseRedefMatch))
2445 return false;
2448 for (auto &Pat : values(ApplyPats)) {
2449 auto *IP = dyn_cast<InstructionPattern>(Pat.get());
2450 if (IP && !ApplyOpTable.addPattern(IP, DiagnoseRedefApply))
2451 return false;
2454 return true;
2457 bool CombineRuleBuilder::parseDefs(const DagInit &Def) {
2458 if (Def.getOperatorAsDef(RuleDef.getLoc())->getName() != "defs") {
2459 PrintError("Expected defs operator");
2460 return false;
2463 SmallVector<StringRef> Roots;
2464 for (unsigned I = 0, E = Def.getNumArgs(); I < E; ++I) {
2465 if (isSpecificDef(*Def.getArg(I), "root")) {
2466 Roots.emplace_back(Def.getArgNameStr(I));
2467 continue;
2470 // Subclasses of GIDefMatchData should declare that this rule needs to pass
2471 // data from the match stage to the apply stage, and ensure that the
2472 // generated matcher has a suitable variable for it to do so.
2473 if (Record *MatchDataRec =
2474 getDefOfSubClass(*Def.getArg(I), "GIDefMatchData")) {
2475 MatchDatas.emplace_back(Def.getArgNameStr(I),
2476 MatchDataRec->getValueAsString("Type"));
2477 continue;
2480 // Otherwise emit an appropriate error message.
2481 if (getDefOfSubClass(*Def.getArg(I), "GIDefKind"))
2482 PrintError("This GIDefKind not implemented in tablegen");
2483 else if (getDefOfSubClass(*Def.getArg(I), "GIDefKindWithArgs"))
2484 PrintError("This GIDefKindWithArgs not implemented in tablegen");
2485 else
2486 PrintError("Expected a subclass of GIDefKind or a sub-dag whose "
2487 "operator is of type GIDefKindWithArgs");
2488 return false;
2491 if (Roots.size() != 1) {
2492 PrintError("Combine rules must have exactly one root");
2493 return false;
2496 RootName = Roots.front();
2498 // Assign variables to all MatchDatas.
2499 AssignMatchDataVariables(MatchDatas);
2500 return true;
2503 bool CombineRuleBuilder::parsePatternList(
2504 const DagInit &List,
2505 function_ref<bool(std::unique_ptr<Pattern>)> ParseAction,
2506 StringRef Operator, ArrayRef<SMLoc> DiagLoc,
2507 StringRef AnonPatNamePrefix) const {
2508 if (List.getOperatorAsDef(RuleDef.getLoc())->getName() != Operator) {
2509 ::PrintError(DiagLoc, "Expected " + Operator + " operator");
2510 return false;
2513 if (List.getNumArgs() == 0) {
2514 ::PrintError(DiagLoc, Operator + " pattern list is empty");
2515 return false;
2518 // The match section consists of a list of matchers and predicates. Parse each
2519 // one and add the equivalent GIMatchDag nodes, predicates, and edges.
2520 for (unsigned I = 0; I < List.getNumArgs(); ++I) {
2521 Init *Arg = List.getArg(I);
2522 std::string Name = List.getArgName(I)
2523 ? List.getArgName(I)->getValue().str()
2524 : makeAnonPatName(AnonPatNamePrefix, I);
2526 if (auto Pat = parseInstructionPattern(*Arg, Name)) {
2527 if (!ParseAction(std::move(Pat)))
2528 return false;
2529 continue;
2532 if (auto Pat = parseWipMatchOpcodeMatcher(*Arg, Name)) {
2533 if (!ParseAction(std::move(Pat)))
2534 return false;
2535 continue;
2538 // Parse arbitrary C++ code
2539 if (const auto *StringI = dyn_cast<StringInit>(Arg)) {
2540 auto CXXPat = std::make_unique<CXXPattern>(*StringI, Name);
2541 if (!ParseAction(std::move(CXXPat)))
2542 return false;
2543 continue;
2546 ::PrintError(DiagLoc,
2547 "Failed to parse pattern: '" + Arg->getAsString() + "'");
2548 return false;
2551 return true;
2554 std::unique_ptr<Pattern>
2555 CombineRuleBuilder::parseInstructionPattern(const Init &Arg,
2556 StringRef Name) const {
2557 const DagInit *DagPat = dyn_cast<DagInit>(&Arg);
2558 if (!DagPat)
2559 return nullptr;
2561 std::unique_ptr<InstructionPattern> Pat;
2562 if (const DagInit *IP = getDagWithOperatorOfSubClass(Arg, "Instruction")) {
2563 auto &Instr = CGT.getInstruction(IP->getOperatorAsDef(RuleDef.getLoc()));
2564 Pat = std::make_unique<CodeGenInstructionPattern>(Instr, Name);
2565 } else if (const DagInit *PFP =
2566 getDagWithOperatorOfSubClass(Arg, PatFragClassName)) {
2567 const Record *Def = PFP->getOperatorAsDef(RuleDef.getLoc());
2568 const PatFrag *PF = parsePatFrag(Def);
2569 if (!PF)
2570 return nullptr; // Already diagnosed by parsePatFrag
2571 Pat = std::make_unique<PatFragPattern>(*PF, Name);
2572 } else if (const DagInit *BP =
2573 getDagWithOperatorOfSubClass(Arg, BuiltinInstClassName)) {
2574 Pat = std::make_unique<BuiltinPattern>(
2575 *BP->getOperatorAsDef(RuleDef.getLoc()), Name);
2576 } else {
2577 return nullptr;
2580 for (unsigned K = 0; K < DagPat->getNumArgs(); ++K) {
2581 if (!parseInstructionPatternOperand(*Pat, DagPat->getArg(K),
2582 DagPat->getArgName(K)))
2583 return nullptr;
2586 if (!Pat->checkSemantics(RuleDef.getLoc()))
2587 return nullptr;
2589 return std::move(Pat);
2592 std::unique_ptr<Pattern>
2593 CombineRuleBuilder::parseWipMatchOpcodeMatcher(const Init &Arg,
2594 StringRef Name) const {
2595 const DagInit *Matcher = getDagWithSpecificOperator(Arg, "wip_match_opcode");
2596 if (!Matcher)
2597 return nullptr;
2599 if (Matcher->getNumArgs() == 0) {
2600 PrintError("Empty wip_match_opcode");
2601 return nullptr;
2604 // Each argument is an opcode that can match.
2605 auto Result = std::make_unique<AnyOpcodePattern>(Name);
2606 for (const auto &Arg : Matcher->getArgs()) {
2607 Record *OpcodeDef = getDefOfSubClass(*Arg, "Instruction");
2608 if (OpcodeDef) {
2609 Result->addOpcode(&CGT.getInstruction(OpcodeDef));
2610 continue;
2613 PrintError("Arguments to wip_match_opcode must be instructions");
2614 return nullptr;
2617 return std::move(Result);
2620 bool CombineRuleBuilder::parseInstructionPatternOperand(
2621 InstructionPattern &IP, const Init *OpInit,
2622 const StringInit *OpName) const {
2623 const auto ParseErr = [&]() {
2624 PrintError("cannot parse operand '" + OpInit->getAsUnquotedString() + "' ");
2625 if (OpName)
2626 PrintNote("operand name is '" + OpName->getAsUnquotedString() + "'");
2627 return false;
2630 // untyped immediate, e.g. 0
2631 if (const auto *IntImm = dyn_cast<IntInit>(OpInit)) {
2632 std::string Name = OpName ? OpName->getAsUnquotedString() : "";
2633 IP.addOperand(IntImm->getValue(), Name, /*Type=*/nullptr);
2634 return true;
2637 // typed immediate, e.g. (i32 0)
2638 if (const auto *DagOp = dyn_cast<DagInit>(OpInit)) {
2639 if (DagOp->getNumArgs() != 1)
2640 return ParseErr();
2642 const Record *TyDef = DagOp->getOperatorAsDef(RuleDef.getLoc());
2643 PatternType ImmTy(TyDef);
2644 if (!ImmTy.isValidType()) {
2645 PrintError("cannot parse immediate '" + OpInit->getAsUnquotedString() +
2646 "', '" + TyDef->getName() + "' is not a ValueType or " +
2647 SpecialTyClassName);
2648 return false;
2651 if (!IP.hasAllDefs()) {
2652 PrintError("out operand of '" + IP.getInstName() +
2653 "' cannot be an immediate");
2654 return false;
2657 const auto *Val = dyn_cast<IntInit>(DagOp->getArg(0));
2658 if (!Val)
2659 return ParseErr();
2661 std::string Name = OpName ? OpName->getAsUnquotedString() : "";
2662 IP.addOperand(Val->getValue(), Name, ImmTy);
2663 return true;
2666 // Typed operand e.g. $x/$z in (G_FNEG $x, $z)
2667 if (auto *DefI = dyn_cast<DefInit>(OpInit)) {
2668 if (!OpName) {
2669 PrintError("expected an operand name after '" + OpInit->getAsString() +
2670 "'");
2671 return false;
2673 const Record *Def = DefI->getDef();
2674 PatternType Ty(Def);
2675 if (!Ty.isValidType()) {
2676 PrintError("invalid operand type: '" + Def->getName() +
2677 "' is not a ValueType");
2678 return false;
2680 IP.addOperand(OpName->getAsUnquotedString(), Ty);
2681 return true;
2684 // Untyped operand e.g. $x/$z in (G_FNEG $x, $z)
2685 if (isa<UnsetInit>(OpInit)) {
2686 assert(OpName && "Unset w/ no OpName?");
2687 IP.addOperand(OpName->getAsUnquotedString(), /*Type=*/nullptr);
2688 return true;
2691 return ParseErr();
2694 std::unique_ptr<PatFrag>
2695 CombineRuleBuilder::parsePatFragImpl(const Record *Def) const {
2696 auto StackTrace = PrettyStackTraceParse(*Def);
2697 if (!Def->isSubClassOf(PatFragClassName))
2698 return nullptr;
2700 const DagInit *Ins = Def->getValueAsDag("InOperands");
2701 if (Ins->getOperatorAsDef(Def->getLoc())->getName() != "ins") {
2702 ::PrintError(Def, "expected 'ins' operator for " + PatFragClassName +
2703 " in operands list");
2704 return nullptr;
2707 const DagInit *Outs = Def->getValueAsDag("OutOperands");
2708 if (Outs->getOperatorAsDef(Def->getLoc())->getName() != "outs") {
2709 ::PrintError(Def, "expected 'outs' operator for " + PatFragClassName +
2710 " out operands list");
2711 return nullptr;
2714 auto Result = std::make_unique<PatFrag>(*Def);
2715 if (!parsePatFragParamList(Def->getLoc(), *Outs,
2716 [&](StringRef Name, PatFrag::ParamKind Kind) {
2717 Result->addOutParam(Name, Kind);
2718 return true;
2720 return nullptr;
2722 if (!parsePatFragParamList(Def->getLoc(), *Ins,
2723 [&](StringRef Name, PatFrag::ParamKind Kind) {
2724 Result->addInParam(Name, Kind);
2725 return true;
2727 return nullptr;
2729 const ListInit *Alts = Def->getValueAsListInit("Alternatives");
2730 unsigned AltIdx = 0;
2731 for (const Init *Alt : *Alts) {
2732 const auto *PatDag = dyn_cast<DagInit>(Alt);
2733 if (!PatDag) {
2734 ::PrintError(Def, "expected dag init for PatFrag pattern alternative");
2735 return nullptr;
2738 PatFrag::Alternative &A = Result->addAlternative();
2739 const auto AddPat = [&](std::unique_ptr<Pattern> Pat) {
2740 A.Pats.push_back(std::move(Pat));
2741 return true;
2744 if (!parsePatternList(
2745 *PatDag, AddPat, "pattern", Def->getLoc(),
2746 /*AnonPatPrefix*/
2747 (Def->getName() + "_alt" + Twine(AltIdx++) + "_pattern").str()))
2748 return nullptr;
2751 if (!Result->buildOperandsTables() || !Result->checkSemantics())
2752 return nullptr;
2754 return Result;
2757 bool CombineRuleBuilder::parsePatFragParamList(
2758 ArrayRef<SMLoc> DiagLoc, const DagInit &OpsList,
2759 function_ref<bool(StringRef, PatFrag::ParamKind)> ParseAction) const {
2760 for (unsigned K = 0; K < OpsList.getNumArgs(); ++K) {
2761 const StringInit *Name = OpsList.getArgName(K);
2762 const Init *Ty = OpsList.getArg(K);
2764 if (!Name) {
2765 ::PrintError(DiagLoc, "all operands must be named'");
2766 return false;
2768 const std::string NameStr = Name->getAsUnquotedString();
2770 PatFrag::ParamKind OpKind;
2771 if (isSpecificDef(*Ty, "gi_imm"))
2772 OpKind = PatFrag::PK_Imm;
2773 else if (isSpecificDef(*Ty, "root"))
2774 OpKind = PatFrag::PK_Root;
2775 else if (isa<UnsetInit>(Ty) ||
2776 isSpecificDef(*Ty, "gi_mo")) // no type = gi_mo.
2777 OpKind = PatFrag::PK_MachineOperand;
2778 else {
2779 ::PrintError(
2780 DiagLoc,
2781 "'" + NameStr +
2782 "' operand type was expected to be 'root', 'gi_imm' or 'gi_mo'");
2783 return false;
2786 if (!ParseAction(NameStr, OpKind))
2787 return false;
2790 return true;
2793 const PatFrag *CombineRuleBuilder::parsePatFrag(const Record *Def) const {
2794 // Cache already parsed PatFrags to avoid doing extra work.
2795 static DenseMap<const Record *, std::unique_ptr<PatFrag>> ParsedPatFrags;
2797 auto It = ParsedPatFrags.find(Def);
2798 if (It != ParsedPatFrags.end()) {
2799 SeenPatFrags.insert(It->second.get());
2800 return It->second.get();
2803 std::unique_ptr<PatFrag> NewPatFrag = parsePatFragImpl(Def);
2804 if (!NewPatFrag) {
2805 ::PrintError(Def, "Could not parse " + PatFragClassName + " '" +
2806 Def->getName() + "'");
2807 // Put a nullptr in the map so we don't attempt parsing this again.
2808 ParsedPatFrags[Def] = nullptr;
2809 return nullptr;
2812 const auto *Res = NewPatFrag.get();
2813 ParsedPatFrags[Def] = std::move(NewPatFrag);
2814 SeenPatFrags.insert(Res);
2815 return Res;
2818 bool CombineRuleBuilder::emitMatchPattern(CodeExpansions &CE,
2819 const PatternAlternatives &Alts,
2820 const InstructionPattern &IP) {
2821 auto StackTrace = PrettyStackTraceEmit(RuleDef, &IP);
2823 auto &M = addRuleMatcher(Alts);
2824 InstructionMatcher &IM = M.addInstructionMatcher("root");
2825 declareInstExpansion(CE, IM, IP.getName());
2827 DenseSet<const Pattern *> SeenPats;
2829 const auto FindOperandDef = [&](StringRef Op) -> InstructionPattern * {
2830 return MatchOpTable.getDef(Op);
2833 if (const auto *CGP = dyn_cast<CodeGenInstructionPattern>(&IP)) {
2834 if (!emitCodeGenInstructionMatchPattern(CE, Alts, M, IM, *CGP, SeenPats,
2835 FindOperandDef))
2836 return false;
2837 } else if (const auto *PFP = dyn_cast<PatFragPattern>(&IP)) {
2838 if (!PFP->getPatFrag().canBeMatchRoot()) {
2839 PrintError("cannot use '" + PFP->getInstName() + " as match root");
2840 return false;
2843 if (!emitPatFragMatchPattern(CE, Alts, M, &IM, *PFP, SeenPats))
2844 return false;
2845 } else if (isa<BuiltinPattern>(&IP)) {
2846 llvm_unreachable("No match builtins known!");
2847 } else
2848 llvm_unreachable("Unknown kind of InstructionPattern!");
2850 // Emit remaining patterns
2851 for (auto &Pat : values(MatchPats)) {
2852 if (SeenPats.contains(Pat.get()))
2853 continue;
2855 switch (Pat->getKind()) {
2856 case Pattern::K_AnyOpcode:
2857 PrintError("wip_match_opcode can not be used with instruction patterns!");
2858 return false;
2859 case Pattern::K_PatFrag: {
2860 if (!emitPatFragMatchPattern(CE, Alts, M, /*IM*/ nullptr,
2861 *cast<PatFragPattern>(Pat.get()), SeenPats))
2862 return false;
2863 continue;
2865 case Pattern::K_Builtin:
2866 PrintError("No known match builtins");
2867 return false;
2868 case Pattern::K_CodeGenInstruction:
2869 cast<InstructionPattern>(Pat.get())->reportUnreachable(RuleDef.getLoc());
2870 return false;
2871 case Pattern::K_CXX: {
2872 addCXXPredicate(M, CE, *cast<CXXPattern>(Pat.get()), Alts);
2873 continue;
2875 default:
2876 llvm_unreachable("unknown pattern kind!");
2880 return emitApplyPatterns(CE, M);
2883 bool CombineRuleBuilder::emitMatchPattern(CodeExpansions &CE,
2884 const PatternAlternatives &Alts,
2885 const AnyOpcodePattern &AOP) {
2886 auto StackTrace = PrettyStackTraceEmit(RuleDef, &AOP);
2888 for (const CodeGenInstruction *CGI : AOP.insts()) {
2889 auto &M = addRuleMatcher(Alts, "wip_match_opcode '" +
2890 CGI->TheDef->getName() + "'");
2892 InstructionMatcher &IM = M.addInstructionMatcher(AOP.getName());
2893 declareInstExpansion(CE, IM, AOP.getName());
2894 // declareInstExpansion needs to be identical, otherwise we need to create a
2895 // CodeExpansions object here instead.
2896 assert(IM.getInsnVarID() == 0);
2898 IM.addPredicate<InstructionOpcodeMatcher>(CGI);
2900 // Emit remaining patterns.
2901 for (auto &Pat : values(MatchPats)) {
2902 if (Pat.get() == &AOP)
2903 continue;
2905 switch (Pat->getKind()) {
2906 case Pattern::K_AnyOpcode:
2907 PrintError("wip_match_opcode can only be present once!");
2908 return false;
2909 case Pattern::K_PatFrag: {
2910 DenseSet<const Pattern *> SeenPats;
2911 if (!emitPatFragMatchPattern(CE, Alts, M, /*IM*/ nullptr,
2912 *cast<PatFragPattern>(Pat.get()),
2913 SeenPats))
2914 return false;
2915 continue;
2917 case Pattern::K_Builtin:
2918 PrintError("No known match builtins");
2919 return false;
2920 case Pattern::K_CodeGenInstruction:
2921 cast<InstructionPattern>(Pat.get())->reportUnreachable(
2922 RuleDef.getLoc());
2923 return false;
2924 case Pattern::K_CXX: {
2925 addCXXPredicate(M, CE, *cast<CXXPattern>(Pat.get()), Alts);
2926 break;
2928 default:
2929 llvm_unreachable("unknown pattern kind!");
2933 if (!emitApplyPatterns(CE, M))
2934 return false;
2937 return true;
2940 bool CombineRuleBuilder::emitPatFragMatchPattern(
2941 CodeExpansions &CE, const PatternAlternatives &Alts, RuleMatcher &RM,
2942 InstructionMatcher *IM, const PatFragPattern &PFP,
2943 DenseSet<const Pattern *> &SeenPats) {
2944 auto StackTrace = PrettyStackTraceEmit(RuleDef, &PFP);
2946 if (SeenPats.contains(&PFP))
2947 return true;
2948 SeenPats.insert(&PFP);
2950 const auto &PF = PFP.getPatFrag();
2952 if (!IM) {
2953 // When we don't have an IM, this means this PatFrag isn't reachable from
2954 // the root. This is only acceptable if it doesn't define anything (e.g. a
2955 // pure C++ PatFrag).
2956 if (PF.num_out_params() != 0) {
2957 PFP.reportUnreachable(RuleDef.getLoc());
2958 return false;
2960 } else {
2961 // When an IM is provided, this is reachable from the root, and we're
2962 // expecting to have output operands.
2963 // TODO: If we want to allow for multiple roots we'll need a map of IMs
2964 // then, and emission becomes a bit more complicated.
2965 assert(PF.num_roots() == 1);
2968 CodeExpansions PatFragCEs;
2969 if (!PFP.mapInputCodeExpansions(CE, PatFragCEs, RuleDef.getLoc()))
2970 return false;
2972 // List of {ParamName, ArgName}.
2973 // When all patterns have been emitted, find expansions in PatFragCEs named
2974 // ArgName and add their expansion to CE using ParamName as the key.
2975 SmallVector<std::pair<std::string, std::string>, 4> CEsToImport;
2977 // Map parameter names to the actual argument.
2978 const auto OperandMapper =
2979 [&](const InstructionOperand &O) -> InstructionOperand {
2980 if (!O.isNamedOperand())
2981 return O;
2983 StringRef ParamName = O.getOperandName();
2985 // Not sure what to do with those tbh. They should probably never be here.
2986 assert(!O.isNamedImmediate() && "TODO: handle named imms");
2987 unsigned PIdx = PF.getParamIdx(ParamName);
2989 // Map parameters to the argument values.
2990 if (PIdx == (unsigned)-1) {
2991 // This is a temp of the PatFragPattern, prefix the name to avoid
2992 // conflicts.
2993 return O.withNewName((PFP.getName() + "." + ParamName).str());
2996 // The operand will be added to PatFragCEs's code expansions using the
2997 // parameter's name. If it's bound to some operand during emission of the
2998 // patterns, we'll want to add it to CE.
2999 auto ArgOp = PFP.getOperand(PIdx);
3000 if (ArgOp.isNamedOperand())
3001 CEsToImport.emplace_back(ArgOp.getOperandName().str(), ParamName);
3003 if (ArgOp.getType() && O.getType() && ArgOp.getType() != O.getType()) {
3004 StringRef PFName = PF.getName();
3005 PrintWarning("impossible type constraints: operand " + Twine(PIdx) +
3006 " of '" + PFP.getName() + "' has type '" +
3007 ArgOp.getType().str() + "', but '" + PFName +
3008 "' constrains it to '" + O.getType().str() + "'");
3009 if (ArgOp.isNamedOperand())
3010 PrintNote("operand " + Twine(PIdx) + " of '" + PFP.getName() +
3011 "' is '" + ArgOp.getOperandName() + "'");
3012 if (O.isNamedOperand())
3013 PrintNote("argument " + Twine(PIdx) + " of '" + PFName + "' is '" +
3014 ParamName + "'");
3017 return ArgOp;
3020 // PatFragPatterns are only made of InstructionPatterns or CXXPatterns.
3021 // Emit instructions from the root.
3022 const auto &FragAlt = PF.getAlternative(Alts.lookup(&PFP));
3023 const auto &FragAltOT = FragAlt.OpTable;
3024 const auto LookupOperandDef =
3025 [&](StringRef Op) -> const InstructionPattern * {
3026 return FragAltOT.getDef(Op);
3029 DenseSet<const Pattern *> PatFragSeenPats;
3030 for (const auto &[Idx, InOp] : enumerate(PF.out_params())) {
3031 if (InOp.Kind != PatFrag::PK_Root)
3032 continue;
3034 StringRef ParamName = InOp.Name;
3035 const auto *Def = FragAltOT.getDef(ParamName);
3036 assert(Def && "PatFrag::checkSemantics should have emitted an error if "
3037 "an out operand isn't defined!");
3038 assert(isa<CodeGenInstructionPattern>(Def) &&
3039 "Nested PatFrags not supported yet");
3041 if (!emitCodeGenInstructionMatchPattern(
3042 PatFragCEs, Alts, RM, *IM, *cast<CodeGenInstructionPattern>(Def),
3043 PatFragSeenPats, LookupOperandDef, OperandMapper))
3044 return false;
3047 // Emit leftovers.
3048 for (const auto &Pat : FragAlt.Pats) {
3049 if (PatFragSeenPats.contains(Pat.get()))
3050 continue;
3052 if (const auto *CXXPat = dyn_cast<CXXPattern>(Pat.get())) {
3053 addCXXPredicate(RM, PatFragCEs, *CXXPat, Alts);
3054 continue;
3057 if (const auto *IP = dyn_cast<InstructionPattern>(Pat.get())) {
3058 IP->reportUnreachable(PF.getLoc());
3059 return false;
3062 llvm_unreachable("Unexpected pattern kind in PatFrag");
3065 for (const auto &[ParamName, ArgName] : CEsToImport) {
3066 // Note: we're find if ParamName already exists. It just means it's been
3067 // bound before, so we prefer to keep the first binding.
3068 CE.declare(ParamName, PatFragCEs.lookup(ArgName));
3071 return true;
3074 bool CombineRuleBuilder::emitApplyPatterns(CodeExpansions &CE, RuleMatcher &M) {
3075 if (hasOnlyCXXApplyPatterns()) {
3076 for (auto &Pat : values(ApplyPats))
3077 addCXXAction(M, CE, *cast<CXXPattern>(Pat.get()));
3078 return true;
3081 DenseSet<const Pattern *> SeenPats;
3082 StringMap<unsigned> OperandToTempRegID;
3084 for (auto *ApplyRoot : ApplyRoots) {
3085 assert(isa<InstructionPattern>(ApplyRoot) &&
3086 "Root can only be a InstructionPattern!");
3087 if (!emitInstructionApplyPattern(CE, M,
3088 cast<InstructionPattern>(*ApplyRoot),
3089 SeenPats, OperandToTempRegID))
3090 return false;
3093 for (auto &Pat : values(ApplyPats)) {
3094 if (SeenPats.contains(Pat.get()))
3095 continue;
3097 switch (Pat->getKind()) {
3098 case Pattern::K_AnyOpcode:
3099 llvm_unreachable("Unexpected pattern in apply!");
3100 case Pattern::K_PatFrag:
3101 // TODO: We could support pure C++ PatFrags as a temporary thing.
3102 llvm_unreachable("Unexpected pattern in apply!");
3103 case Pattern::K_Builtin:
3104 if (!emitInstructionApplyPattern(CE, M, cast<BuiltinPattern>(*Pat),
3105 SeenPats, OperandToTempRegID))
3106 return false;
3107 break;
3108 case Pattern::K_CodeGenInstruction:
3109 cast<CodeGenInstructionPattern>(*Pat).reportUnreachable(RuleDef.getLoc());
3110 return false;
3111 case Pattern::K_CXX: {
3112 addCXXAction(M, CE, *cast<CXXPattern>(Pat.get()));
3113 continue;
3115 default:
3116 llvm_unreachable("unknown pattern kind!");
3120 return true;
3123 bool CombineRuleBuilder::emitInstructionApplyPattern(
3124 CodeExpansions &CE, RuleMatcher &M, const InstructionPattern &P,
3125 DenseSet<const Pattern *> &SeenPats,
3126 StringMap<unsigned> &OperandToTempRegID) {
3127 auto StackTrace = PrettyStackTraceEmit(RuleDef, &P);
3129 if (SeenPats.contains(&P))
3130 return true;
3132 SeenPats.insert(&P);
3134 // First, render the uses.
3135 for (auto &Op : P.named_operands()) {
3136 if (Op.isDef())
3137 continue;
3139 StringRef OpName = Op.getOperandName();
3140 if (const auto *DefPat = ApplyOpTable.getDef(OpName)) {
3141 if (!emitInstructionApplyPattern(CE, M, *DefPat, SeenPats,
3142 OperandToTempRegID))
3143 return false;
3144 } else {
3145 // If we have no def, check this exists in the MatchRoot.
3146 if (!Op.isNamedImmediate() && !MatchOpTable.lookup(OpName).Found) {
3147 PrintError("invalid output operand '" + OpName +
3148 "': operand is not a live-in of the match pattern, and it "
3149 "has no definition");
3150 return false;
3155 if (const auto *BP = dyn_cast<BuiltinPattern>(&P))
3156 return emitBuiltinApplyPattern(CE, M, *BP, OperandToTempRegID);
3158 if (isa<PatFragPattern>(&P))
3159 llvm_unreachable("PatFragPatterns is not supported in 'apply'!");
3161 auto &CGIP = cast<CodeGenInstructionPattern>(P);
3163 // Now render this inst.
3164 auto &DstMI =
3165 M.addAction<BuildMIAction>(M.allocateOutputInsnID(), &CGIP.getInst());
3167 for (auto &Op : P.operands()) {
3168 if (Op.isNamedImmediate()) {
3169 PrintError("invalid output operand '" + Op.getOperandName() +
3170 "': output immediates cannot be named");
3171 PrintNote("while emitting pattern '" + P.getName() + "' (" +
3172 P.getInstName() + ")");
3173 return false;
3176 if (Op.hasImmValue()) {
3177 if (!emitCodeGenInstructionApplyImmOperand(M, DstMI, CGIP, Op))
3178 return false;
3179 continue;
3182 StringRef OpName = Op.getOperandName();
3184 // Uses of operand.
3185 if (!Op.isDef()) {
3186 if (auto It = OperandToTempRegID.find(OpName);
3187 It != OperandToTempRegID.end()) {
3188 assert(!MatchOpTable.lookup(OpName).Found &&
3189 "Temp reg is also from match pattern?");
3190 DstMI.addRenderer<TempRegRenderer>(It->second);
3191 } else {
3192 // This should be a match live in or a redef of a matched instr.
3193 // If it's a use of a temporary register, then we messed up somewhere -
3194 // the previous condition should have passed.
3195 assert(MatchOpTable.lookup(OpName).Found &&
3196 !ApplyOpTable.getDef(OpName) && "Temp reg not emitted yet!");
3197 DstMI.addRenderer<CopyRenderer>(OpName);
3199 continue;
3202 // Determine what we're dealing with. Are we replace a matched instruction?
3203 // Creating a new one?
3204 auto OpLookupRes = MatchOpTable.lookup(OpName);
3205 if (OpLookupRes.Found) {
3206 if (OpLookupRes.isLiveIn()) {
3207 // live-in of the match pattern.
3208 PrintError("Cannot define live-in operand '" + OpName +
3209 "' in the 'apply' pattern");
3210 return false;
3212 assert(OpLookupRes.Def);
3214 // TODO: Handle this. We need to mutate the instr, or delete the old
3215 // one.
3216 // Likewise, we also need to ensure we redef everything, if the
3217 // instr has more than one def, we need to redef all or nothing.
3218 if (OpLookupRes.Def != MatchRoot) {
3219 PrintError("redefining an instruction other than the root is not "
3220 "supported (operand '" +
3221 OpName + "')");
3222 return false;
3224 // redef of a match
3225 DstMI.addRenderer<CopyRenderer>(OpName);
3226 continue;
3229 // Define a new register unique to the apply patterns (AKA a "temp"
3230 // register).
3231 unsigned TempRegID;
3232 if (auto It = OperandToTempRegID.find(OpName);
3233 It != OperandToTempRegID.end()) {
3234 TempRegID = It->second;
3235 } else {
3236 // This is a brand new register.
3237 TempRegID = M.allocateTempRegID();
3238 OperandToTempRegID[OpName] = TempRegID;
3239 const auto Ty = Op.getType();
3240 if (!Ty) {
3241 PrintError("def of a new register '" + OpName +
3242 "' in the apply patterns must have a type");
3243 return false;
3246 declareTempRegExpansion(CE, TempRegID, OpName);
3247 // Always insert the action at the beginning, otherwise we may end up
3248 // using the temp reg before it's available.
3249 M.insertAction<MakeTempRegisterAction>(
3250 M.actions_begin(), Ty.getLLTCodeGenOrTempType(M), TempRegID);
3253 DstMI.addRenderer<TempRegRenderer>(TempRegID);
3256 // TODO: works?
3257 DstMI.chooseInsnToMutate(M);
3258 declareInstExpansion(CE, DstMI, P.getName());
3260 return true;
3263 bool CombineRuleBuilder::emitCodeGenInstructionApplyImmOperand(
3264 RuleMatcher &M, BuildMIAction &DstMI, const CodeGenInstructionPattern &P,
3265 const InstructionOperand &O) {
3266 // If we have a type, we implicitly emit a G_CONSTANT, except for G_CONSTANT
3267 // itself where we emit a CImm.
3269 // No type means we emit a simple imm.
3270 // G_CONSTANT is a special case and needs a CImm though so this is likely a
3271 // mistake.
3272 const bool isGConstant = P.is("G_CONSTANT");
3273 const auto Ty = O.getType();
3274 if (!Ty) {
3275 if (isGConstant) {
3276 PrintError("'G_CONSTANT' immediate must be typed!");
3277 PrintNote("while emitting pattern '" + P.getName() + "' (" +
3278 P.getInstName() + ")");
3279 return false;
3282 DstMI.addRenderer<ImmRenderer>(O.getImmValue());
3283 return true;
3286 auto ImmTy = Ty.getLLTCodeGenOrTempType(M);
3288 if (isGConstant) {
3289 DstMI.addRenderer<ImmRenderer>(O.getImmValue(), ImmTy);
3290 return true;
3293 unsigned TempRegID = M.allocateTempRegID();
3294 // Ensure MakeTempReg & the BuildConstantAction occur at the beginning.
3295 auto InsertIt = M.insertAction<MakeTempRegisterAction>(M.actions_begin(),
3296 ImmTy, TempRegID);
3297 M.insertAction<BuildConstantAction>(++InsertIt, TempRegID, O.getImmValue());
3298 DstMI.addRenderer<TempRegRenderer>(TempRegID);
3299 return true;
3302 bool CombineRuleBuilder::emitBuiltinApplyPattern(
3303 CodeExpansions &CE, RuleMatcher &M, const BuiltinPattern &P,
3304 StringMap<unsigned> &OperandToTempRegID) {
3305 const auto Error = [&](Twine Reason) {
3306 PrintError("cannot emit '" + P.getInstName() + "' builtin: " + Reason);
3307 return false;
3310 switch (P.getBuiltinKind()) {
3311 case BI_EraseRoot: {
3312 // Root is always inst 0.
3313 M.addAction<EraseInstAction>(/*InsnID*/ 0);
3314 return true;
3316 case BI_ReplaceReg: {
3317 StringRef Old = P.getOperand(0).getOperandName();
3318 StringRef New = P.getOperand(1).getOperandName();
3320 if (!ApplyOpTable.lookup(New).Found && !MatchOpTable.lookup(New).Found)
3321 return Error("unknown operand '" + Old + "'");
3323 auto &OldOM = M.getOperandMatcher(Old);
3324 if (auto It = OperandToTempRegID.find(New);
3325 It != OperandToTempRegID.end()) {
3326 // Replace with temp reg.
3327 M.addAction<ReplaceRegAction>(OldOM.getInsnVarID(), OldOM.getOpIdx(),
3328 It->second);
3329 } else {
3330 // Replace with matched reg.
3331 auto &NewOM = M.getOperandMatcher(New);
3332 M.addAction<ReplaceRegAction>(OldOM.getInsnVarID(), OldOM.getOpIdx(),
3333 NewOM.getInsnVarID(), NewOM.getOpIdx());
3335 // checkSemantics should have ensured that we can only rewrite the root.
3336 // Ensure we're deleting it.
3337 assert(MatchOpTable.getDef(Old) == MatchRoot);
3338 // TODO: We could avoid adding the action again if it's already in. The
3339 // MatchTable is smart enough to only emit one opcode even if
3340 // EraseInstAction is present multiple times. I think searching for a copy
3341 // is more expensive than just blindly adding it though.
3342 M.addAction<EraseInstAction>(/*InsnID*/ 0);
3344 return true;
3348 llvm_unreachable("Unknown BuiltinKind!");
3351 bool isLiteralImm(const InstructionPattern &P, unsigned OpIdx) {
3352 if (const auto *CGP = dyn_cast<CodeGenInstructionPattern>(&P)) {
3353 StringRef InstName = CGP->getInst().TheDef->getName();
3354 return (InstName == "G_CONSTANT" || InstName == "G_FCONSTANT") &&
3355 OpIdx == 1;
3358 llvm_unreachable("TODO");
3361 bool CombineRuleBuilder::emitCodeGenInstructionMatchPattern(
3362 CodeExpansions &CE, const PatternAlternatives &Alts, RuleMatcher &M,
3363 InstructionMatcher &IM, const CodeGenInstructionPattern &P,
3364 DenseSet<const Pattern *> &SeenPats, OperandDefLookupFn LookupOperandDef,
3365 OperandMapperFnRef OperandMapper) {
3366 auto StackTrace = PrettyStackTraceEmit(RuleDef, &P);
3368 if (SeenPats.contains(&P))
3369 return true;
3371 SeenPats.insert(&P);
3373 IM.addPredicate<InstructionOpcodeMatcher>(&P.getInst());
3374 declareInstExpansion(CE, IM, P.getName());
3376 for (const auto &[Idx, OriginalO] : enumerate(P.operands())) {
3377 // Remap the operand. This is used when emitting InstructionPatterns inside
3378 // PatFrags, so it can remap them to the arguments passed to the pattern.
3380 // We use the remapped operand to emit immediates, and for the symbolic
3381 // operand names (in IM.addOperand). CodeExpansions and OperandTable lookups
3382 // still use the original name.
3384 // The "def" flag on the remapped operand is always ignored.
3385 auto RemappedO = OperandMapper(OriginalO);
3386 assert(RemappedO.isNamedOperand() == OriginalO.isNamedOperand() &&
3387 "Cannot remap an unnamed operand to a named one!");
3389 const auto OpName =
3390 RemappedO.isNamedOperand() ? RemappedO.getOperandName().str() : "";
3391 OperandMatcher &OM =
3392 IM.addOperand(Idx, OpName, AllocatedTemporariesBaseID++);
3393 if (!OpName.empty())
3394 declareOperandExpansion(CE, OM, OriginalO.getOperandName());
3396 // Handle immediates.
3397 if (RemappedO.hasImmValue()) {
3398 if (isLiteralImm(P, Idx))
3399 OM.addPredicate<LiteralIntOperandMatcher>(RemappedO.getImmValue());
3400 else
3401 OM.addPredicate<ConstantIntOperandMatcher>(RemappedO.getImmValue());
3404 // Handle typed operands, but only bother to check if it hasn't been done
3405 // before.
3407 // getOperandMatcher will always return the first OM to have been created
3408 // for that Operand. "OM" here is always a new OperandMatcher.
3410 // Always emit a check for unnamed operands.
3411 if (OpName.empty() ||
3412 !M.getOperandMatcher(OpName).contains<LLTOperandMatcher>()) {
3413 if (const auto Ty = RemappedO.getType()) {
3414 // TODO: We could support GITypeOf here on the condition that the
3415 // OperandMatcher exists already. Though it's clunky to make this work
3416 // and isn't all that useful so it's just rejected in typecheckPatterns
3417 // at this time.
3418 assert(Ty.isLLT() && "Only LLTs are supported in match patterns!");
3419 OM.addPredicate<LLTOperandMatcher>(Ty.getLLTCodeGen());
3423 // Stop here if the operand is a def, or if it had no name.
3424 if (OriginalO.isDef() || !OriginalO.isNamedOperand())
3425 continue;
3427 const auto *DefPat = LookupOperandDef(OriginalO.getOperandName());
3428 if (!DefPat)
3429 continue;
3431 if (OriginalO.hasImmValue()) {
3432 assert(!OpName.empty());
3433 // This is a named immediate that also has a def, that's not okay.
3434 // e.g.
3435 // (G_SEXT $y, (i32 0))
3436 // (COPY $x, 42:$y)
3437 PrintError("'" + OpName +
3438 "' is a named immediate, it cannot be defined by another "
3439 "instruction");
3440 PrintNote("'" + OpName + "' is defined by '" + DefPat->getName() + "'");
3441 return false;
3444 // From here we know that the operand defines an instruction, and we need to
3445 // emit it.
3446 auto InstOpM =
3447 OM.addPredicate<InstructionOperandMatcher>(M, DefPat->getName());
3448 if (!InstOpM) {
3449 // TODO: copy-pasted from GlobalISelEmitter.cpp. Is it still relevant
3450 // here?
3451 PrintError("Nested instruction '" + DefPat->getName() +
3452 "' cannot be the same as another operand '" +
3453 OriginalO.getOperandName() + "'");
3454 return false;
3457 auto &IM = (*InstOpM)->getInsnMatcher();
3458 if (const auto *CGIDef = dyn_cast<CodeGenInstructionPattern>(DefPat)) {
3459 if (!emitCodeGenInstructionMatchPattern(CE, Alts, M, IM, *CGIDef,
3460 SeenPats, LookupOperandDef,
3461 OperandMapper))
3462 return false;
3463 continue;
3466 if (const auto *PFPDef = dyn_cast<PatFragPattern>(DefPat)) {
3467 if (!emitPatFragMatchPattern(CE, Alts, M, &IM, *PFPDef, SeenPats))
3468 return false;
3469 continue;
3472 llvm_unreachable("unknown type of InstructionPattern");
3475 return true;
3478 //===- GICombinerEmitter --------------------------------------------------===//
3480 /// Main implementation class. This emits the tablegenerated output.
3482 /// It collects rules, uses `CombineRuleBuilder` to parse them and accumulate
3483 /// RuleMatchers, then takes all the necessary state/data from the various
3484 /// static storage pools and wires them together to emit the match table &
3485 /// associated function/data structures.
3486 class GICombinerEmitter final : public GlobalISelMatchTableExecutorEmitter {
3487 RecordKeeper &Records;
3488 StringRef Name;
3489 const CodeGenTarget &Target;
3490 Record *Combiner;
3491 unsigned NextRuleID = 0;
3493 // List all combine rules (ID, name) imported.
3494 // Note that the combiner rule ID is different from the RuleMatcher ID. The
3495 // latter is internal to the MatchTable, the former is the canonical ID of the
3496 // combine rule used to disable/enable it.
3497 std::vector<std::pair<unsigned, std::string>> AllCombineRules;
3499 // Keep track of all rules we've seen so far to ensure we don't process
3500 // the same rule twice.
3501 StringSet<> RulesSeen;
3503 MatchTable buildMatchTable(MutableArrayRef<RuleMatcher> Rules);
3505 void emitRuleConfigImpl(raw_ostream &OS);
3507 void emitAdditionalImpl(raw_ostream &OS) override;
3509 void emitMIPredicateFns(raw_ostream &OS) override;
3510 void emitI64ImmPredicateFns(raw_ostream &OS) override;
3511 void emitAPFloatImmPredicateFns(raw_ostream &OS) override;
3512 void emitAPIntImmPredicateFns(raw_ostream &OS) override;
3513 void emitTestSimplePredicate(raw_ostream &OS) override;
3514 void emitRunCustomAction(raw_ostream &OS) override;
3516 void emitAdditionalTemporariesDecl(raw_ostream &OS,
3517 StringRef Indent) override;
3519 const CodeGenTarget &getTarget() const override { return Target; }
3520 StringRef getClassName() const override {
3521 return Combiner->getValueAsString("Classname");
3524 StringRef getCombineAllMethodName() const {
3525 return Combiner->getValueAsString("CombineAllMethodName");
3528 std::string getRuleConfigClassName() const {
3529 return getClassName().str() + "RuleConfig";
3532 void gatherRules(std::vector<RuleMatcher> &Rules,
3533 const std::vector<Record *> &&RulesAndGroups);
3535 public:
3536 explicit GICombinerEmitter(RecordKeeper &RK, const CodeGenTarget &Target,
3537 StringRef Name, Record *Combiner);
3538 ~GICombinerEmitter() {}
3540 void run(raw_ostream &OS);
3543 void GICombinerEmitter::emitRuleConfigImpl(raw_ostream &OS) {
3544 OS << "struct " << getRuleConfigClassName() << " {\n"
3545 << " SparseBitVector<> DisabledRules;\n\n"
3546 << " bool isRuleEnabled(unsigned RuleID) const;\n"
3547 << " bool parseCommandLineOption();\n"
3548 << " bool setRuleEnabled(StringRef RuleIdentifier);\n"
3549 << " bool setRuleDisabled(StringRef RuleIdentifier);\n"
3550 << "};\n\n";
3552 std::vector<std::pair<std::string, std::string>> Cases;
3553 Cases.reserve(AllCombineRules.size());
3555 for (const auto &[ID, Name] : AllCombineRules)
3556 Cases.emplace_back(Name, "return " + to_string(ID) + ";\n");
3558 OS << "static std::optional<uint64_t> getRuleIdxForIdentifier(StringRef "
3559 "RuleIdentifier) {\n"
3560 << " uint64_t I;\n"
3561 << " // getAtInteger(...) returns false on success\n"
3562 << " bool Parsed = !RuleIdentifier.getAsInteger(0, I);\n"
3563 << " if (Parsed)\n"
3564 << " return I;\n\n"
3565 << "#ifndef NDEBUG\n";
3566 StringMatcher Matcher("RuleIdentifier", Cases, OS);
3567 Matcher.Emit();
3568 OS << "#endif // ifndef NDEBUG\n\n"
3569 << " return std::nullopt;\n"
3570 << "}\n";
3572 OS << "static std::optional<std::pair<uint64_t, uint64_t>> "
3573 "getRuleRangeForIdentifier(StringRef RuleIdentifier) {\n"
3574 << " std::pair<StringRef, StringRef> RangePair = "
3575 "RuleIdentifier.split('-');\n"
3576 << " if (!RangePair.second.empty()) {\n"
3577 << " const auto First = "
3578 "getRuleIdxForIdentifier(RangePair.first);\n"
3579 << " const auto Last = "
3580 "getRuleIdxForIdentifier(RangePair.second);\n"
3581 << " if (!First || !Last)\n"
3582 << " return std::nullopt;\n"
3583 << " if (First >= Last)\n"
3584 << " report_fatal_error(\"Beginning of range should be before "
3585 "end of range\");\n"
3586 << " return {{*First, *Last + 1}};\n"
3587 << " }\n"
3588 << " if (RangePair.first == \"*\") {\n"
3589 << " return {{0, " << AllCombineRules.size() << "}};\n"
3590 << " }\n"
3591 << " const auto I = getRuleIdxForIdentifier(RangePair.first);\n"
3592 << " if (!I)\n"
3593 << " return std::nullopt;\n"
3594 << " return {{*I, *I + 1}};\n"
3595 << "}\n\n";
3597 for (bool Enabled : {true, false}) {
3598 OS << "bool " << getRuleConfigClassName() << "::setRule"
3599 << (Enabled ? "Enabled" : "Disabled") << "(StringRef RuleIdentifier) {\n"
3600 << " auto MaybeRange = getRuleRangeForIdentifier(RuleIdentifier);\n"
3601 << " if (!MaybeRange)\n"
3602 << " return false;\n"
3603 << " for (auto I = MaybeRange->first; I < MaybeRange->second; ++I)\n"
3604 << " DisabledRules." << (Enabled ? "reset" : "set") << "(I);\n"
3605 << " return true;\n"
3606 << "}\n\n";
3609 OS << "static std::vector<std::string> " << Name << "Option;\n"
3610 << "static cl::list<std::string> " << Name << "DisableOption(\n"
3611 << " \"" << Name.lower() << "-disable-rule\",\n"
3612 << " cl::desc(\"Disable one or more combiner rules temporarily in "
3613 << "the " << Name << " pass\"),\n"
3614 << " cl::CommaSeparated,\n"
3615 << " cl::Hidden,\n"
3616 << " cl::cat(GICombinerOptionCategory),\n"
3617 << " cl::callback([](const std::string &Str) {\n"
3618 << " " << Name << "Option.push_back(Str);\n"
3619 << " }));\n"
3620 << "static cl::list<std::string> " << Name << "OnlyEnableOption(\n"
3621 << " \"" << Name.lower() << "-only-enable-rule\",\n"
3622 << " cl::desc(\"Disable all rules in the " << Name
3623 << " pass then re-enable the specified ones\"),\n"
3624 << " cl::Hidden,\n"
3625 << " cl::cat(GICombinerOptionCategory),\n"
3626 << " cl::callback([](const std::string &CommaSeparatedArg) {\n"
3627 << " StringRef Str = CommaSeparatedArg;\n"
3628 << " " << Name << "Option.push_back(\"*\");\n"
3629 << " do {\n"
3630 << " auto X = Str.split(\",\");\n"
3631 << " " << Name << "Option.push_back((\"!\" + X.first).str());\n"
3632 << " Str = X.second;\n"
3633 << " } while (!Str.empty());\n"
3634 << " }));\n"
3635 << "\n\n"
3636 << "bool " << getRuleConfigClassName()
3637 << "::isRuleEnabled(unsigned RuleID) const {\n"
3638 << " return !DisabledRules.test(RuleID);\n"
3639 << "}\n"
3640 << "bool " << getRuleConfigClassName() << "::parseCommandLineOption() {\n"
3641 << " for (StringRef Identifier : " << Name << "Option) {\n"
3642 << " bool Enabled = Identifier.consume_front(\"!\");\n"
3643 << " if (Enabled && !setRuleEnabled(Identifier))\n"
3644 << " return false;\n"
3645 << " if (!Enabled && !setRuleDisabled(Identifier))\n"
3646 << " return false;\n"
3647 << " }\n"
3648 << " return true;\n"
3649 << "}\n\n";
3652 void GICombinerEmitter::emitAdditionalImpl(raw_ostream &OS) {
3653 OS << "bool " << getClassName() << "::" << getCombineAllMethodName()
3654 << "(MachineInstr &I) const {\n"
3655 << " const TargetSubtargetInfo &ST = MF.getSubtarget();\n"
3656 << " const PredicateBitset AvailableFeatures = "
3657 "getAvailableFeatures();\n"
3658 << " B.setInstrAndDebugLoc(I);\n"
3659 << " State.MIs.clear();\n"
3660 << " State.MIs.push_back(&I);\n"
3661 << " " << MatchDataInfo::StructName << " = "
3662 << MatchDataInfo::StructTypeName << "();\n\n"
3663 << " if (executeMatchTable(*this, State, ExecInfo, B"
3664 << ", getMatchTable(), *ST.getInstrInfo(), MRI, "
3665 "*MRI.getTargetRegisterInfo(), *ST.getRegBankInfo(), AvailableFeatures"
3666 << ", /*CoverageInfo*/ nullptr)) {\n"
3667 << " return true;\n"
3668 << " }\n\n"
3669 << " return false;\n"
3670 << "}\n\n";
3673 void GICombinerEmitter::emitMIPredicateFns(raw_ostream &OS) {
3674 auto MatchCode = CXXPredicateCode::getAllMatchCode();
3675 emitMIPredicateFnsImpl<const CXXPredicateCode *>(
3676 OS, "", ArrayRef<const CXXPredicateCode *>(MatchCode),
3677 [](const CXXPredicateCode *C) -> StringRef { return C->BaseEnumName; },
3678 [](const CXXPredicateCode *C) -> StringRef { return C->Code; });
3681 void GICombinerEmitter::emitI64ImmPredicateFns(raw_ostream &OS) {
3682 // Unused, but still needs to be called.
3683 emitImmPredicateFnsImpl<unsigned>(
3684 OS, "I64", "int64_t", {}, [](unsigned) { return ""; },
3685 [](unsigned) { return ""; });
3688 void GICombinerEmitter::emitAPFloatImmPredicateFns(raw_ostream &OS) {
3689 // Unused, but still needs to be called.
3690 emitImmPredicateFnsImpl<unsigned>(
3691 OS, "APFloat", "const APFloat &", {}, [](unsigned) { return ""; },
3692 [](unsigned) { return ""; });
3695 void GICombinerEmitter::emitAPIntImmPredicateFns(raw_ostream &OS) {
3696 // Unused, but still needs to be called.
3697 emitImmPredicateFnsImpl<unsigned>(
3698 OS, "APInt", "const APInt &", {}, [](unsigned) { return ""; },
3699 [](unsigned) { return ""; });
3702 void GICombinerEmitter::emitTestSimplePredicate(raw_ostream &OS) {
3703 if (!AllCombineRules.empty()) {
3704 OS << "enum {\n";
3705 std::string EnumeratorSeparator = " = GICXXPred_Invalid + 1,\n";
3706 // To avoid emitting a switch, we expect that all those rules are in order.
3707 // That way we can just get the RuleID from the enum by subtracting
3708 // (GICXXPred_Invalid + 1).
3709 unsigned ExpectedID = 0;
3710 (void)ExpectedID;
3711 for (const auto &ID : keys(AllCombineRules)) {
3712 assert(ExpectedID++ == ID && "combine rules are not ordered!");
3713 OS << " " << getIsEnabledPredicateEnumName(ID) << EnumeratorSeparator;
3714 EnumeratorSeparator = ",\n";
3716 OS << "};\n\n";
3719 OS << "bool " << getClassName()
3720 << "::testSimplePredicate(unsigned Predicate) const {\n"
3721 << " return RuleConfig.isRuleEnabled(Predicate - "
3722 "GICXXPred_Invalid - "
3723 "1);\n"
3724 << "}\n";
3727 void GICombinerEmitter::emitRunCustomAction(raw_ostream &OS) {
3728 const auto ApplyCode = CXXPredicateCode::getAllApplyCode();
3730 if (!ApplyCode.empty()) {
3731 OS << "enum {\n";
3732 std::string EnumeratorSeparator = " = GICXXCustomAction_Invalid + 1,\n";
3733 for (const auto &Apply : ApplyCode) {
3734 OS << " " << Apply->getEnumNameWithPrefix(CXXApplyPrefix)
3735 << EnumeratorSeparator;
3736 EnumeratorSeparator = ",\n";
3738 OS << "};\n";
3741 OS << "void " << getClassName()
3742 << "::runCustomAction(unsigned ApplyID, const MatcherState &State, "
3743 "NewMIVector &OutMIs) const "
3744 "{\n";
3745 if (!ApplyCode.empty()) {
3746 OS << " switch(ApplyID) {\n";
3747 for (const auto &Apply : ApplyCode) {
3748 OS << " case " << Apply->getEnumNameWithPrefix(CXXApplyPrefix) << ":{\n"
3749 << " " << join(split(Apply->Code, "\n"), "\n ") << "\n"
3750 << " return;\n";
3751 OS << " }\n";
3753 OS << "}\n";
3755 OS << " llvm_unreachable(\"Unknown Apply Action\");\n"
3756 << "}\n";
3759 void GICombinerEmitter::emitAdditionalTemporariesDecl(raw_ostream &OS,
3760 StringRef Indent) {
3761 OS << Indent << "struct " << MatchDataInfo::StructTypeName << " {\n";
3762 for (const auto &[Type, VarNames] : AllMatchDataVars) {
3763 assert(!VarNames.empty() && "Cannot have no vars for this type!");
3764 OS << Indent << " " << Type << " " << join(VarNames, ", ") << ";\n";
3766 OS << Indent << "};\n"
3767 << Indent << "mutable " << MatchDataInfo::StructTypeName << " "
3768 << MatchDataInfo::StructName << ";\n\n";
3771 GICombinerEmitter::GICombinerEmitter(RecordKeeper &RK,
3772 const CodeGenTarget &Target,
3773 StringRef Name, Record *Combiner)
3774 : Records(RK), Name(Name), Target(Target), Combiner(Combiner) {}
3776 MatchTable
3777 GICombinerEmitter::buildMatchTable(MutableArrayRef<RuleMatcher> Rules) {
3778 std::vector<Matcher *> InputRules;
3779 for (Matcher &Rule : Rules)
3780 InputRules.push_back(&Rule);
3782 unsigned CurrentOrdering = 0;
3783 StringMap<unsigned> OpcodeOrder;
3784 for (RuleMatcher &Rule : Rules) {
3785 const StringRef Opcode = Rule.getOpcode();
3786 assert(!Opcode.empty() && "Didn't expect an undefined opcode");
3787 if (OpcodeOrder.count(Opcode) == 0)
3788 OpcodeOrder[Opcode] = CurrentOrdering++;
3791 llvm::stable_sort(InputRules, [&OpcodeOrder](const Matcher *A,
3792 const Matcher *B) {
3793 auto *L = static_cast<const RuleMatcher *>(A);
3794 auto *R = static_cast<const RuleMatcher *>(B);
3795 return std::make_tuple(OpcodeOrder[L->getOpcode()], L->getNumOperands()) <
3796 std::make_tuple(OpcodeOrder[R->getOpcode()], R->getNumOperands());
3799 for (Matcher *Rule : InputRules)
3800 Rule->optimize();
3802 std::vector<std::unique_ptr<Matcher>> MatcherStorage;
3803 std::vector<Matcher *> OptRules =
3804 optimizeRules<GroupMatcher>(InputRules, MatcherStorage);
3806 for (Matcher *Rule : OptRules)
3807 Rule->optimize();
3809 OptRules = optimizeRules<SwitchMatcher>(OptRules, MatcherStorage);
3811 return MatchTable::buildTable(OptRules, /*WithCoverage*/ false,
3812 /*IsCombiner*/ true);
3815 /// Recurse into GICombineGroup's and flatten the ruleset into a simple list.
3816 void GICombinerEmitter::gatherRules(
3817 std::vector<RuleMatcher> &ActiveRules,
3818 const std::vector<Record *> &&RulesAndGroups) {
3819 for (Record *Rec : RulesAndGroups) {
3820 if (!Rec->isValueUnset("Rules")) {
3821 gatherRules(ActiveRules, Rec->getValueAsListOfDefs("Rules"));
3822 continue;
3825 StringRef RuleName = Rec->getName();
3826 if (!RulesSeen.insert(RuleName).second) {
3827 PrintWarning(Rec->getLoc(),
3828 "skipping rule '" + Rec->getName() +
3829 "' because it has already been processed");
3830 continue;
3833 AllCombineRules.emplace_back(NextRuleID, Rec->getName().str());
3834 CombineRuleBuilder CRB(Target, SubtargetFeatures, *Rec, NextRuleID++,
3835 ActiveRules);
3837 if (!CRB.parseAll()) {
3838 assert(ErrorsPrinted && "Parsing failed without errors!");
3839 continue;
3842 if (StopAfterParse) {
3843 CRB.print(outs());
3844 continue;
3847 if (!CRB.emitRuleMatchers()) {
3848 assert(ErrorsPrinted && "Emission failed without errors!");
3849 continue;
3854 void GICombinerEmitter::run(raw_ostream &OS) {
3855 InstructionOpcodeMatcher::initOpcodeValuesMap(Target);
3856 LLTOperandMatcher::initTypeIDValuesMap();
3858 Records.startTimer("Gather rules");
3859 std::vector<RuleMatcher> Rules;
3860 gatherRules(Rules, Combiner->getValueAsListOfDefs("Rules"));
3861 if (ErrorsPrinted)
3862 PrintFatalError(Combiner->getLoc(), "Failed to parse one or more rules");
3864 if (StopAfterParse)
3865 return;
3867 Records.startTimer("Creating Match Table");
3868 unsigned MaxTemporaries = 0;
3869 for (const auto &Rule : Rules)
3870 MaxTemporaries = std::max(MaxTemporaries, Rule.countRendererFns());
3872 llvm::stable_sort(Rules, [&](const RuleMatcher &A, const RuleMatcher &B) {
3873 if (A.isHigherPriorityThan(B)) {
3874 assert(!B.isHigherPriorityThan(A) && "Cannot be more important "
3875 "and less important at "
3876 "the same time");
3877 return true;
3879 return false;
3882 const MatchTable Table = buildMatchTable(Rules);
3884 Records.startTimer("Emit combiner");
3886 emitSourceFileHeader(getClassName().str() + " Combiner Match Table", OS);
3888 // Unused
3889 std::vector<StringRef> CustomRendererFns;
3890 // Unused
3891 std::vector<Record *> ComplexPredicates;
3893 SmallVector<LLTCodeGen, 16> TypeObjects;
3894 append_range(TypeObjects, KnownTypes);
3895 llvm::sort(TypeObjects);
3897 // Hack: Avoid empty declarator.
3898 if (TypeObjects.empty())
3899 TypeObjects.push_back(LLT::scalar(1));
3901 // GET_GICOMBINER_DEPS, which pulls in extra dependencies.
3902 OS << "#ifdef GET_GICOMBINER_DEPS\n"
3903 << "#include \"llvm/ADT/SparseBitVector.h\"\n"
3904 << "namespace llvm {\n"
3905 << "extern cl::OptionCategory GICombinerOptionCategory;\n"
3906 << "} // end namespace llvm\n"
3907 << "#endif // ifdef GET_GICOMBINER_DEPS\n\n";
3909 // GET_GICOMBINER_TYPES, which needs to be included before the declaration of
3910 // the class.
3911 OS << "#ifdef GET_GICOMBINER_TYPES\n";
3912 emitRuleConfigImpl(OS);
3913 OS << "#endif // ifdef GET_GICOMBINER_TYPES\n\n";
3914 emitPredicateBitset(OS, "GET_GICOMBINER_TYPES");
3916 // GET_GICOMBINER_CLASS_MEMBERS, which need to be included inside the class.
3917 emitPredicatesDecl(OS, "GET_GICOMBINER_CLASS_MEMBERS");
3918 emitTemporariesDecl(OS, "GET_GICOMBINER_CLASS_MEMBERS");
3920 // GET_GICOMBINER_IMPL, which needs to be included outside the class.
3921 emitExecutorImpl(OS, Table, TypeObjects, Rules, ComplexPredicates,
3922 CustomRendererFns, "GET_GICOMBINER_IMPL");
3924 // GET_GICOMBINER_CONSTRUCTOR_INITS, which are in the constructor's
3925 // initializer list.
3926 emitPredicatesInit(OS, "GET_GICOMBINER_CONSTRUCTOR_INITS");
3927 emitTemporariesInit(OS, MaxTemporaries, "GET_GICOMBINER_CONSTRUCTOR_INITS");
3930 } // end anonymous namespace
3932 //===----------------------------------------------------------------------===//
3934 static void EmitGICombiner(RecordKeeper &RK, raw_ostream &OS) {
3935 EnablePrettyStackTrace();
3936 CodeGenTarget Target(RK);
3938 if (SelectedCombiners.empty())
3939 PrintFatalError("No combiners selected with -combiners");
3940 for (const auto &Combiner : SelectedCombiners) {
3941 Record *CombinerDef = RK.getDef(Combiner);
3942 if (!CombinerDef)
3943 PrintFatalError("Could not find " + Combiner);
3944 GICombinerEmitter(RK, Target, Combiner, CombinerDef).run(OS);
3948 static TableGen::Emitter::Opt X("gen-global-isel-combiner", EmitGICombiner,
3949 "Generate GlobalISel Combiner");