[llvm] 991d04d - Revert "[NFC][TableGen][GlobalISel] Move MIR Pattern Parsing out of Combiner Impl (#80257)"
via llvm-commits
llvm-commits at lists.llvm.org
Mon Feb 5 01:00:38 PST 2024
Author: pvanhout
Date: 2024-02-05T10:00:08+01:00
New Revision: 991d04d7213bf2747583413ac9b98c7163cf679d
URL: https://github.com/llvm/llvm-project/commit/991d04d7213bf2747583413ac9b98c7163cf679d
DIFF: https://github.com/llvm/llvm-project/commit/991d04d7213bf2747583413ac9b98c7163cf679d.diff
LOG: Revert "[NFC][TableGen][GlobalISel] Move MIR Pattern Parsing out of Combiner Impl (#80257)"
This reverts commit cfa0833ccc7450a322e709583e894e4c96ce682e.
Added:
Modified:
llvm/utils/TableGen/GlobalISel/CMakeLists.txt
llvm/utils/TableGen/GlobalISel/CombinerUtils.h
llvm/utils/TableGen/GlobalISel/Patterns.cpp
llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp
Removed:
llvm/utils/TableGen/GlobalISel/CombinerUtils.cpp
llvm/utils/TableGen/GlobalISel/PatternParser.cpp
llvm/utils/TableGen/GlobalISel/PatternParser.h
################################################################################
diff --git a/llvm/utils/TableGen/GlobalISel/CMakeLists.txt b/llvm/utils/TableGen/GlobalISel/CMakeLists.txt
index eb0b1504c0ca5..eed7d3a15b676 100644
--- a/llvm/utils/TableGen/GlobalISel/CMakeLists.txt
+++ b/llvm/utils/TableGen/GlobalISel/CMakeLists.txt
@@ -5,10 +5,8 @@ set(LLVM_LINK_COMPONENTS
add_llvm_library(LLVMTableGenGlobalISel STATIC OBJECT EXCLUDE_FROM_ALL
CodeExpander.cpp
- CombinerUtils.cpp
CXXPredicates.cpp
MatchDataInfo.cpp
- PatternParser.cpp
Patterns.cpp
$<TARGET_OBJECTS:obj.LLVMTableGenCommon>
@@ -18,6 +16,6 @@ add_llvm_library(LLVMTableGenGlobalISel STATIC OBJECT EXCLUDE_FROM_ALL
# Users may include its headers as "GlobalISel/*.h"
target_include_directories(LLVMTableGenGlobalISel
- PUBLIC
+ INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>
)
diff --git a/llvm/utils/TableGen/GlobalISel/CombinerUtils.cpp b/llvm/utils/TableGen/GlobalISel/CombinerUtils.cpp
deleted file mode 100644
index 37e6306050951..0000000000000
--- a/llvm/utils/TableGen/GlobalISel/CombinerUtils.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-//===- CombinerUtils.cpp --------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "CombinerUtils.h"
-#include "llvm/ADT/StringSet.h"
-
-namespace llvm {
-
-StringRef insertStrRef(StringRef S) {
- if (S.empty())
- return {};
-
- static StringSet<> Pool;
- auto [It, Inserted] = Pool.insert(S);
- return It->getKey();
-}
-
-} // namespace llvm
diff --git a/llvm/utils/TableGen/GlobalISel/CombinerUtils.h b/llvm/utils/TableGen/GlobalISel/CombinerUtils.h
index 82a64c63edbde..8cb2514a10e87 100644
--- a/llvm/utils/TableGen/GlobalISel/CombinerUtils.h
+++ b/llvm/utils/TableGen/GlobalISel/CombinerUtils.h
@@ -65,10 +65,6 @@ inline const DagInit *getDagWithOperatorOfSubClass(const Init &N,
return I;
return nullptr;
}
-
-/// Copies a StringRef into a static pool to preserve it.
-StringRef insertStrRef(StringRef S);
-
} // namespace llvm
#endif
diff --git a/llvm/utils/TableGen/GlobalISel/PatternParser.cpp b/llvm/utils/TableGen/GlobalISel/PatternParser.cpp
deleted file mode 100644
index 8f2ff9b119dfa..0000000000000
--- a/llvm/utils/TableGen/GlobalISel/PatternParser.cpp
+++ /dev/null
@@ -1,462 +0,0 @@
-//===- PatternParser.cpp ----------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "PatternParser.h"
-#include "CodeGenIntrinsics.h"
-#include "CodeGenTarget.h"
-#include "CombinerUtils.h"
-#include "Patterns.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/PrettyStackTrace.h"
-#include "llvm/Support/SaveAndRestore.h"
-#include "llvm/TableGen/Error.h"
-#include "llvm/TableGen/Record.h"
-
-namespace llvm {
-namespace gi {
-static constexpr StringLiteral MIFlagsEnumClassName = "MIFlagEnum";
-
-namespace {
-class PrettyStackTraceParse : public PrettyStackTraceEntry {
- const Record &Def;
-
-public:
- PrettyStackTraceParse(const Record &Def) : Def(Def) {}
-
- void print(raw_ostream &OS) const override {
- if (Def.isSubClassOf("GICombineRule"))
- OS << "Parsing GICombineRule '" << Def.getName() << "'";
- else if (Def.isSubClassOf(PatFrag::ClassName))
- OS << "Parsing " << PatFrag::ClassName << " '" << Def.getName() << "'";
- else
- OS << "Parsing '" << Def.getName() << "'";
- OS << '\n';
- }
-};
-} // namespace
-
-bool PatternParser::parsePatternList(
- const DagInit &List,
- function_ref<bool(std::unique_ptr<Pattern>)> ParseAction,
- StringRef Operator, StringRef AnonPatNamePrefix) {
- if (List.getOperatorAsDef(DiagLoc)->getName() != Operator) {
- PrintError(DiagLoc, "Expected " + Operator + " operator");
- return false;
- }
-
- if (List.getNumArgs() == 0) {
- PrintError(DiagLoc, Operator + " pattern list is empty");
- return false;
- }
-
- // The match section consists of a list of matchers and predicates. Parse each
- // one and add the equivalent GIMatchDag nodes, predicates, and edges.
- for (unsigned I = 0; I < List.getNumArgs(); ++I) {
- Init *Arg = List.getArg(I);
- std::string Name = List.getArgName(I)
- ? List.getArgName(I)->getValue().str()
- : ("__" + AnonPatNamePrefix + "_" + Twine(I)).str();
-
- if (auto Pat = parseInstructionPattern(*Arg, Name)) {
- if (!ParseAction(std::move(Pat)))
- return false;
- continue;
- }
-
- if (auto Pat = parseWipMatchOpcodeMatcher(*Arg, Name)) {
- if (!ParseAction(std::move(Pat)))
- return false;
- continue;
- }
-
- // Parse arbitrary C++ code
- if (const auto *StringI = dyn_cast<StringInit>(Arg)) {
- auto CXXPat = std::make_unique<CXXPattern>(*StringI, insertStrRef(Name));
- if (!ParseAction(std::move(CXXPat)))
- return false;
- continue;
- }
-
- PrintError(DiagLoc,
- "Failed to parse pattern: '" + Arg->getAsString() + "'");
- return false;
- }
-
- return true;
-}
-
-static const CodeGenInstruction &
-getInstrForIntrinsic(const CodeGenTarget &CGT, const CodeGenIntrinsic *I) {
- StringRef Opc;
- if (I->isConvergent) {
- Opc = I->hasSideEffects ? "G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS"
- : "G_INTRINSIC_CONVERGENT";
- } else {
- Opc = I->hasSideEffects ? "G_INTRINSIC_W_SIDE_EFFECTS" : "G_INTRINSIC";
- }
-
- RecordKeeper &RK = I->TheDef->getRecords();
- return CGT.getInstruction(RK.getDef(Opc));
-}
-
-static const CodeGenIntrinsic *getCodeGenIntrinsic(Record *R) {
- // Intrinsics need to have a static lifetime because the match table keeps
- // references to CodeGenIntrinsic objects.
- static DenseMap<const Record *, std::unique_ptr<CodeGenIntrinsic>>
- AllIntrinsics;
-
- auto &Ptr = AllIntrinsics[R];
- if (!Ptr)
- Ptr = std::make_unique<CodeGenIntrinsic>(R, std::vector<Record *>());
- return Ptr.get();
-}
-
-std::unique_ptr<Pattern>
-PatternParser::parseInstructionPattern(const Init &Arg, StringRef Name) {
- const DagInit *DagPat = dyn_cast<DagInit>(&Arg);
- if (!DagPat)
- return nullptr;
-
- std::unique_ptr<InstructionPattern> Pat;
- if (const DagInit *IP = getDagWithOperatorOfSubClass(Arg, "Instruction")) {
- auto &Instr = CGT.getInstruction(IP->getOperatorAsDef(DiagLoc));
- Pat =
- std::make_unique<CodeGenInstructionPattern>(Instr, insertStrRef(Name));
- } else if (const DagInit *IP =
- getDagWithOperatorOfSubClass(Arg, "Intrinsic")) {
- Record *TheDef = IP->getOperatorAsDef(DiagLoc);
- const CodeGenIntrinsic *Intrin = getCodeGenIntrinsic(TheDef);
- const CodeGenInstruction &Instr = getInstrForIntrinsic(CGT, Intrin);
- Pat =
- std::make_unique<CodeGenInstructionPattern>(Instr, insertStrRef(Name));
- cast<CodeGenInstructionPattern>(*Pat).setIntrinsic(Intrin);
- } else if (const DagInit *PFP =
- getDagWithOperatorOfSubClass(Arg, PatFrag::ClassName)) {
- const Record *Def = PFP->getOperatorAsDef(DiagLoc);
- const PatFrag *PF = parsePatFrag(Def);
- if (!PF)
- return nullptr; // Already diagnosed by parsePatFrag
- Pat = std::make_unique<PatFragPattern>(*PF, insertStrRef(Name));
- } else if (const DagInit *BP =
- getDagWithOperatorOfSubClass(Arg, BuiltinPattern::ClassName)) {
- Pat = std::make_unique<BuiltinPattern>(*BP->getOperatorAsDef(DiagLoc),
- insertStrRef(Name));
- } else
- return nullptr;
-
- for (unsigned K = 0; K < DagPat->getNumArgs(); ++K) {
- Init *Arg = DagPat->getArg(K);
- if (auto *DagArg = getDagWithSpecificOperator(*Arg, "MIFlags")) {
- if (!parseInstructionPatternMIFlags(*Pat, DagArg))
- return nullptr;
- continue;
- }
-
- if (!parseInstructionPatternOperand(*Pat, Arg, DagPat->getArgName(K)))
- return nullptr;
- }
-
- if (!Pat->checkSemantics(DiagLoc))
- return nullptr;
-
- return std::move(Pat);
-}
-
-std::unique_ptr<Pattern>
-PatternParser::parseWipMatchOpcodeMatcher(const Init &Arg, StringRef Name) {
- const DagInit *Matcher = getDagWithSpecificOperator(Arg, "wip_match_opcode");
- if (!Matcher)
- return nullptr;
-
- if (Matcher->getNumArgs() == 0) {
- PrintError(DiagLoc, "Empty wip_match_opcode");
- return nullptr;
- }
-
- // Each argument is an opcode that can match.
- auto Result = std::make_unique<AnyOpcodePattern>(insertStrRef(Name));
- for (const auto &Arg : Matcher->getArgs()) {
- Record *OpcodeDef = getDefOfSubClass(*Arg, "Instruction");
- if (OpcodeDef) {
- Result->addOpcode(&CGT.getInstruction(OpcodeDef));
- continue;
- }
-
- PrintError(DiagLoc, "Arguments to wip_match_opcode must be instructions");
- return nullptr;
- }
-
- return std::move(Result);
-}
-
-bool PatternParser::parseInstructionPatternOperand(InstructionPattern &IP,
- const Init *OpInit,
- const StringInit *OpName) {
- const auto ParseErr = [&]() {
- PrintError(DiagLoc,
- "cannot parse operand '" + OpInit->getAsUnquotedString() + "' ");
- if (OpName)
- PrintNote(DiagLoc,
- "operand name is '" + OpName->getAsUnquotedString() + "'");
- return false;
- };
-
- // untyped immediate, e.g. 0
- if (const auto *IntImm = dyn_cast<IntInit>(OpInit)) {
- std::string Name = OpName ? OpName->getAsUnquotedString() : "";
- IP.addOperand(IntImm->getValue(), insertStrRef(Name), PatternType());
- return true;
- }
-
- // typed immediate, e.g. (i32 0)
- if (const auto *DagOp = dyn_cast<DagInit>(OpInit)) {
- if (DagOp->getNumArgs() != 1)
- return ParseErr();
-
- const Record *TyDef = DagOp->getOperatorAsDef(DiagLoc);
- auto ImmTy = PatternType::get(DiagLoc, TyDef,
- "cannot parse immediate '" +
- DagOp->getAsUnquotedString() + "'");
- if (!ImmTy)
- return false;
-
- if (!IP.hasAllDefs()) {
- PrintError(DiagLoc, "out operand of '" + IP.getInstName() +
- "' cannot be an immediate");
- return false;
- }
-
- const auto *Val = dyn_cast<IntInit>(DagOp->getArg(0));
- if (!Val)
- return ParseErr();
-
- std::string Name = OpName ? OpName->getAsUnquotedString() : "";
- IP.addOperand(Val->getValue(), insertStrRef(Name), *ImmTy);
- return true;
- }
-
- // Typed operand e.g. $x/$z in (G_FNEG $x, $z)
- if (auto *DefI = dyn_cast<DefInit>(OpInit)) {
- if (!OpName) {
- PrintError(DiagLoc, "expected an operand name after '" +
- OpInit->getAsString() + "'");
- return false;
- }
- const Record *Def = DefI->getDef();
- auto Ty = PatternType::get(DiagLoc, Def, "cannot parse operand type");
- if (!Ty)
- return false;
- IP.addOperand(insertStrRef(OpName->getAsUnquotedString()), *Ty);
- return true;
- }
-
- // Untyped operand e.g. $x/$z in (G_FNEG $x, $z)
- if (isa<UnsetInit>(OpInit)) {
- assert(OpName && "Unset w/ no OpName?");
- IP.addOperand(insertStrRef(OpName->getAsUnquotedString()), PatternType());
- return true;
- }
-
- return ParseErr();
-}
-
-bool PatternParser::parseInstructionPatternMIFlags(InstructionPattern &IP,
- const DagInit *Op) {
- auto *CGIP = dyn_cast<CodeGenInstructionPattern>(&IP);
- if (!CGIP) {
- PrintError(DiagLoc,
- "matching/writing MIFlags is only allowed on CodeGenInstruction "
- "patterns");
- return false;
- }
-
- const auto CheckFlagEnum = [&](const Record *R) {
- if (!R->isSubClassOf(MIFlagsEnumClassName)) {
- PrintError(DiagLoc, "'" + R->getName() + "' is not a subclass of '" +
- MIFlagsEnumClassName + "'");
- return false;
- }
-
- return true;
- };
-
- if (CGIP->getMIFlagsInfo()) {
- PrintError(DiagLoc, "MIFlags can only be present once on an instruction");
- return false;
- }
-
- auto &FI = CGIP->getOrCreateMIFlagsInfo();
- for (unsigned K = 0; K < Op->getNumArgs(); ++K) {
- const Init *Arg = Op->getArg(K);
-
- // Match/set a flag: (MIFlags FmNoNans)
- if (const auto *Def = dyn_cast<DefInit>(Arg)) {
- const Record *R = Def->getDef();
- if (!CheckFlagEnum(R))
- return false;
-
- FI.addSetFlag(R);
- continue;
- }
-
- // Do not match a flag/unset a flag: (MIFlags (not FmNoNans))
- if (const DagInit *NotDag = getDagWithSpecificOperator(*Arg, "not")) {
- for (const Init *NotArg : NotDag->getArgs()) {
- const DefInit *DefArg = dyn_cast<DefInit>(NotArg);
- if (!DefArg) {
- PrintError(DiagLoc, "cannot parse '" + NotArg->getAsUnquotedString() +
- "': expected a '" + MIFlagsEnumClassName +
- "'");
- return false;
- }
-
- const Record *R = DefArg->getDef();
- if (!CheckFlagEnum(R))
- return false;
-
- FI.addUnsetFlag(R);
- continue;
- }
-
- continue;
- }
-
- // Copy flags from a matched instruction: (MIFlags $mi)
- if (isa<UnsetInit>(Arg)) {
- FI.addCopyFlag(insertStrRef(Op->getArgName(K)->getAsUnquotedString()));
- continue;
- }
- }
-
- return true;
-}
-
-std::unique_ptr<PatFrag> PatternParser::parsePatFragImpl(const Record *Def) {
- auto StackTrace = PrettyStackTraceParse(*Def);
- if (!Def->isSubClassOf(PatFrag::ClassName))
- return nullptr;
-
- const DagInit *Ins = Def->getValueAsDag("InOperands");
- if (Ins->getOperatorAsDef(Def->getLoc())->getName() != "ins") {
- PrintError(Def, "expected 'ins' operator for " + PatFrag::ClassName +
- " in operands list");
- return nullptr;
- }
-
- const DagInit *Outs = Def->getValueAsDag("OutOperands");
- if (Outs->getOperatorAsDef(Def->getLoc())->getName() != "outs") {
- PrintError(Def, "expected 'outs' operator for " + PatFrag::ClassName +
- " out operands list");
- return nullptr;
- }
-
- auto Result = std::make_unique<PatFrag>(*Def);
- if (!parsePatFragParamList(*Outs, [&](StringRef Name, unsigned Kind) {
- Result->addOutParam(insertStrRef(Name), (PatFrag::ParamKind)Kind);
- return true;
- }))
- return nullptr;
-
- if (!parsePatFragParamList(*Ins, [&](StringRef Name, unsigned Kind) {
- Result->addInParam(insertStrRef(Name), (PatFrag::ParamKind)Kind);
- return true;
- }))
- return nullptr;
-
- const ListInit *Alts = Def->getValueAsListInit("Alternatives");
- unsigned AltIdx = 0;
- for (const Init *Alt : *Alts) {
- const auto *PatDag = dyn_cast<DagInit>(Alt);
- if (!PatDag) {
- PrintError(Def, "expected dag init for PatFrag pattern alternative");
- return nullptr;
- }
-
- PatFrag::Alternative &A = Result->addAlternative();
- const auto AddPat = [&](std::unique_ptr<Pattern> Pat) {
- A.Pats.push_back(std::move(Pat));
- return true;
- };
-
- SaveAndRestore<ArrayRef<SMLoc>> DiagLocSAR(DiagLoc, Def->getLoc());
- if (!parsePatternList(
- *PatDag, AddPat, "pattern",
- /*AnonPatPrefix*/
- (Def->getName() + "_alt" + Twine(AltIdx++) + "_pattern").str()))
- return nullptr;
- }
-
- if (!Result->buildOperandsTables() || !Result->checkSemantics())
- return nullptr;
-
- return Result;
-}
-
-bool PatternParser::parsePatFragParamList(
- const DagInit &OpsList,
- function_ref<bool(StringRef, unsigned)> ParseAction) {
- for (unsigned K = 0; K < OpsList.getNumArgs(); ++K) {
- const StringInit *Name = OpsList.getArgName(K);
- const Init *Ty = OpsList.getArg(K);
-
- if (!Name) {
- PrintError(DiagLoc, "all operands must be named'");
- return false;
- }
- const std::string NameStr = Name->getAsUnquotedString();
-
- PatFrag::ParamKind OpKind;
- if (isSpecificDef(*Ty, "gi_imm"))
- OpKind = PatFrag::PK_Imm;
- else if (isSpecificDef(*Ty, "root"))
- OpKind = PatFrag::PK_Root;
- else if (isa<UnsetInit>(Ty) ||
- isSpecificDef(*Ty, "gi_mo")) // no type = gi_mo.
- OpKind = PatFrag::PK_MachineOperand;
- else {
- PrintError(
- DiagLoc,
- "'" + NameStr +
- "' operand type was expected to be 'root', 'gi_imm' or 'gi_mo'");
- return false;
- }
-
- if (!ParseAction(NameStr, (unsigned)OpKind))
- return false;
- }
-
- return true;
-}
-
-const PatFrag *PatternParser::parsePatFrag(const Record *Def) {
- // Cache already parsed PatFrags to avoid doing extra work.
- static DenseMap<const Record *, std::unique_ptr<PatFrag>> ParsedPatFrags;
-
- auto It = ParsedPatFrags.find(Def);
- if (It != ParsedPatFrags.end()) {
- SeenPatFrags.insert(It->second.get());
- return It->second.get();
- }
-
- std::unique_ptr<PatFrag> NewPatFrag = parsePatFragImpl(Def);
- if (!NewPatFrag) {
- PrintError(Def, "Could not parse " + PatFrag::ClassName + " '" +
- Def->getName() + "'");
- // Put a nullptr in the map so we don't attempt parsing this again.
- ParsedPatFrags[Def] = nullptr;
- return nullptr;
- }
-
- const auto *Res = NewPatFrag.get();
- ParsedPatFrags[Def] = std::move(NewPatFrag);
- SeenPatFrags.insert(Res);
- return Res;
-}
-
-} // namespace gi
-} // namespace llvm
diff --git a/llvm/utils/TableGen/GlobalISel/PatternParser.h b/llvm/utils/TableGen/GlobalISel/PatternParser.h
deleted file mode 100644
index cd6f524075cdb..0000000000000
--- a/llvm/utils/TableGen/GlobalISel/PatternParser.h
+++ /dev/null
@@ -1,118 +0,0 @@
-//===- PatternParser.h ------------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-/// \file Contains tools to parse MIR patterns from TableGen DAG elements.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_UTILS_GLOBALISEL_PATTERNPARSER_H
-#define LLVM_UTILS_GLOBALISEL_PATTERNPARSER_H
-
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/STLFunctionalExtras.h"
-#include "llvm/ADT/SmallPtrSet.h"
-#include "llvm/Support/SMLoc.h"
-#include <memory>
-
-namespace llvm {
-class CodeGenTarget;
-class DagInit;
-class Init;
-class Record;
-class StringRef;
-class StringInit;
-
-namespace gi {
-class InstructionPattern;
-class Pattern;
-class PatFrag;
-
-/// Helper class to parse MIR Pattern lists.
-///
-/// e.g., `(match (G_FADD $x, $y, $z), (G_FNEG $y, $z))`
-class PatternParser {
- const CodeGenTarget &CGT;
- ArrayRef<SMLoc> DiagLoc;
-
- mutable SmallPtrSet<const PatFrag *, 2> SeenPatFrags;
-
-public:
- PatternParser(const CodeGenTarget &CGT, ArrayRef<SMLoc> DiagLoc)
- : CGT(CGT), DiagLoc(DiagLoc) {}
-
- /// Parses a list of patterns such as:
- /// (Operator (Pattern1 ...), (Pattern2 ...))
- /// \param List DagInit of the expected pattern list.
- /// \param ParseAction Callback to handle a succesfully parsed pattern.
- /// \param Operator The name of the operator, e.g. "match"
- /// \param AnonPatNamePrefix Prefix for anonymous pattern names.
- /// \return true on success, false on failure.
- bool
- parsePatternList(const DagInit &List,
- function_ref<bool(std::unique_ptr<Pattern>)> ParseAction,
- StringRef Operator, StringRef AnonPatNamePrefix);
-
- /// \returns all PatFrags encountered by this PatternParser.
- const auto &getSeenPatFrags() const { return SeenPatFrags; }
-
-private:
- /// Parse any InstructionPattern from a TableGen Init.
- /// \param Arg Init to parse.
- /// \param PatName Name of the pattern that will be parsed.
- /// \return the parsed pattern on success, nullptr on failure.
- std::unique_ptr<Pattern> parseInstructionPattern(const Init &Arg,
- StringRef PatName);
-
- /// Parse a WipOpcodeMatcher from a TableGen Init.
- /// \param Arg Init to parse.
- /// \param PatName Name of the pattern that will be parsed.
- /// \return the parsed pattern on success, nullptr on failure.
- std::unique_ptr<Pattern> parseWipMatchOpcodeMatcher(const Init &Arg,
- StringRef PatName);
-
- /// Parses an Operand of an InstructionPattern from a TableGen Init.
- /// \param IP InstructionPattern for which we're parsing.
- /// \param OpInit Init to parse.
- /// \param OpName Name of the operand to parse.
- /// \return true on success, false on failure.
- bool parseInstructionPatternOperand(InstructionPattern &IP,
- const Init *OpInit,
- const StringInit *OpName);
-
- /// Parses a MIFlag for an InstructionPattern from a TableGen Init.
- /// \param IP InstructionPattern for which we're parsing.
- /// \param Op Init to parse.
- /// \return true on success, false on failure.
- bool parseInstructionPatternMIFlags(InstructionPattern &IP,
- const DagInit *Op);
-
- /// (Uncached) PatFrag parsing implementation.
- /// \param Def PatFrag def to parsee.
- /// \return the parsed PatFrag on success, nullptr on failure.
- std::unique_ptr<PatFrag> parsePatFragImpl(const Record *Def);
-
- /// Parses the in or out parameter list of a PatFrag.
- /// \param OpsList Init to parse.
- /// \param ParseAction Callback on successful parse, with the name of
- /// the parameter and its \ref PatFrag::ParamKind
- /// \return true on success, false on failure.
- bool
- parsePatFragParamList(const DagInit &OpsList,
- function_ref<bool(StringRef, unsigned)> ParseAction);
-
- /// Cached PatFrag parser. This avoids duplicate work by keeping track of
- /// already-parsed PatFrags.
- /// \param Def PatFrag def to parsee.
- /// \return the parsed PatFrag on success, nullptr on failure.
- const PatFrag *parsePatFrag(const Record *Def);
-};
-
-} // namespace gi
-} // namespace llvm
-
-#endif
diff --git a/llvm/utils/TableGen/GlobalISel/Patterns.cpp b/llvm/utils/TableGen/GlobalISel/Patterns.cpp
index f5422f56e7a1b..758eac2dfebd3 100644
--- a/llvm/utils/TableGen/GlobalISel/Patterns.cpp
+++ b/llvm/utils/TableGen/GlobalISel/Patterns.cpp
@@ -7,11 +7,11 @@
//===----------------------------------------------------------------------===//
#include "Patterns.h"
+#include "../CodeGenInstruction.h"
+#include "../CodeGenIntrinsics.h"
#include "CXXPredicates.h"
#include "CodeExpander.h"
#include "CodeExpansions.h"
-#include "CodeGenInstruction.h"
-#include "CodeGenIntrinsics.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
diff --git a/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp b/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp
index df33abc1b139c..d9249cf627f21 100644
--- a/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp
+++ b/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp
@@ -34,7 +34,6 @@
#include "GlobalISel/CodeExpansions.h"
#include "GlobalISel/CombinerUtils.h"
#include "GlobalISel/MatchDataInfo.h"
-#include "GlobalISel/PatternParser.h"
#include "GlobalISel/Patterns.h"
#include "GlobalISelMatchTable.h"
#include "GlobalISelMatchTableExecutorEmitter.h"
@@ -81,6 +80,7 @@ cl::opt<bool> DebugTypeInfer("gicombiner-debug-typeinfer",
constexpr StringLiteral CXXApplyPrefix = "GICXXCustomAction_CombineApply";
constexpr StringLiteral CXXPredPrefix = "GICXXPred_MI_Predicate_";
+constexpr StringLiteral MIFlagsEnumClassName = "MIFlagEnum";
//===- CodeExpansions Helpers --------------------------------------------===//
@@ -109,6 +109,17 @@ void declareTempRegExpansion(CodeExpansions &CE, unsigned TempRegID,
//===- Misc. Helpers -----------------------------------------------------===//
+/// Copies a StringRef into a static pool to preserve it.
+/// Most Pattern classes use StringRef so we need this.
+StringRef insertStrRef(StringRef S) {
+ if (S.empty())
+ return {};
+
+ static StringSet<> Pool;
+ auto [It, Inserted] = Pool.insert(S);
+ return It->getKey();
+}
+
template <typename Container> auto keys(Container &&C) {
return map_range(C, [](auto &Entry) -> auto & { return Entry.first; });
}
@@ -628,9 +639,8 @@ class CombineRuleBuilder {
SubtargetFeatureInfoMap &SubtargetFeatures,
Record &RuleDef, unsigned ID,
std::vector<RuleMatcher> &OutRMs)
- : Parser(CGT, RuleDef.getLoc()), CGT(CGT),
- SubtargetFeatures(SubtargetFeatures), RuleDef(RuleDef), RuleID(ID),
- OutRMs(OutRMs) {}
+ : CGT(CGT), SubtargetFeatures(SubtargetFeatures), RuleDef(RuleDef),
+ RuleID(ID), OutRMs(OutRMs) {}
/// Parses all fields in the RuleDef record.
bool parseAll();
@@ -708,6 +718,26 @@ class CombineRuleBuilder {
bool buildRuleOperandsTable();
bool parseDefs(const DagInit &Def);
+ bool
+ parsePatternList(const DagInit &List,
+ function_ref<bool(std::unique_ptr<Pattern>)> ParseAction,
+ StringRef Operator, ArrayRef<SMLoc> DiagLoc,
+ StringRef AnonPatNamePrefix) const;
+
+ std::unique_ptr<Pattern> parseInstructionPattern(const Init &Arg,
+ StringRef PatName) const;
+ std::unique_ptr<Pattern> parseWipMatchOpcodeMatcher(const Init &Arg,
+ StringRef PatName) const;
+ bool parseInstructionPatternOperand(InstructionPattern &IP,
+ const Init *OpInit,
+ const StringInit *OpName) const;
+ bool parseInstructionPatternMIFlags(InstructionPattern &IP,
+ const DagInit *Op) const;
+ std::unique_ptr<PatFrag> parsePatFragImpl(const Record *Def) const;
+ bool parsePatFragParamList(
+ ArrayRef<SMLoc> DiagLoc, const DagInit &OpsList,
+ function_ref<bool(StringRef, PatFrag::ParamKind)> ParseAction) const;
+ const PatFrag *parsePatFrag(const Record *Def) const;
bool emitMatchPattern(CodeExpansions &CE, const PatternAlternatives &Alts,
const InstructionPattern &IP);
@@ -751,7 +781,6 @@ class CombineRuleBuilder {
DenseSet<const Pattern *> &SeenPats, OperandDefLookupFn LookupOperandDef,
OperandMapperFnRef OperandMapper = [](const auto &O) { return O; });
- PatternParser Parser;
const CodeGenTarget &CGT;
SubtargetFeatureInfoMap &SubtargetFeatures;
Record &RuleDef;
@@ -779,6 +808,9 @@ class CombineRuleBuilder {
SmallVector<MatchDataInfo, 2> MatchDatas;
SmallVector<PatternAlternatives, 1> PermutationsToEmit;
+
+ // print()/debug-only members.
+ mutable SmallPtrSet<const PatFrag *, 2> SeenPatFrags;
};
bool CombineRuleBuilder::parseAll() {
@@ -787,16 +819,16 @@ bool CombineRuleBuilder::parseAll() {
if (!parseDefs(*RuleDef.getValueAsDag("Defs")))
return false;
- if (!Parser.parsePatternList(
+ if (!parsePatternList(
*RuleDef.getValueAsDag("Match"),
[this](auto Pat) { return addMatchPattern(std::move(Pat)); }, "match",
- (RuleDef.getName() + "_match").str()))
+ RuleDef.getLoc(), (RuleDef.getName() + "_match").str()))
return false;
- if (!Parser.parsePatternList(
+ if (!parsePatternList(
*RuleDef.getValueAsDag("Apply"),
[this](auto Pat) { return addApplyPattern(std::move(Pat)); }, "apply",
- (RuleDef.getName() + "_apply").str()))
+ RuleDef.getLoc(), (RuleDef.getName() + "_apply").str()))
return false;
if (!buildRuleOperandsTable() || !typecheckPatterns() || !findRoots() ||
@@ -852,10 +884,9 @@ void CombineRuleBuilder::print(raw_ostream &OS) const {
OS << " )\n";
}
- const auto &SeenPFs = Parser.getSeenPatFrags();
- if (!SeenPFs.empty()) {
+ if (!SeenPatFrags.empty()) {
OS << " (PatFrags\n";
- for (const auto *PF : Parser.getSeenPatFrags()) {
+ for (const auto *PF : SeenPatFrags) {
PF->print(OS, /*Indent=*/" ");
OS << '\n';
}
@@ -1469,6 +1500,426 @@ bool CombineRuleBuilder::parseDefs(const DagInit &Def) {
return true;
}
+bool CombineRuleBuilder::parsePatternList(
+ const DagInit &List,
+ function_ref<bool(std::unique_ptr<Pattern>)> ParseAction,
+ StringRef Operator, ArrayRef<SMLoc> DiagLoc,
+ StringRef AnonPatNamePrefix) const {
+ if (List.getOperatorAsDef(RuleDef.getLoc())->getName() != Operator) {
+ ::PrintError(DiagLoc, "Expected " + Operator + " operator");
+ return false;
+ }
+
+ if (List.getNumArgs() == 0) {
+ ::PrintError(DiagLoc, Operator + " pattern list is empty");
+ return false;
+ }
+
+ // The match section consists of a list of matchers and predicates. Parse each
+ // one and add the equivalent GIMatchDag nodes, predicates, and edges.
+ for (unsigned I = 0; I < List.getNumArgs(); ++I) {
+ Init *Arg = List.getArg(I);
+ std::string Name = List.getArgName(I)
+ ? List.getArgName(I)->getValue().str()
+ : ("__" + AnonPatNamePrefix + "_" + Twine(I)).str();
+
+ if (auto Pat = parseInstructionPattern(*Arg, Name)) {
+ if (!ParseAction(std::move(Pat)))
+ return false;
+ continue;
+ }
+
+ if (auto Pat = parseWipMatchOpcodeMatcher(*Arg, Name)) {
+ if (!ParseAction(std::move(Pat)))
+ return false;
+ continue;
+ }
+
+ // Parse arbitrary C++ code
+ if (const auto *StringI = dyn_cast<StringInit>(Arg)) {
+ auto CXXPat = std::make_unique<CXXPattern>(*StringI, insertStrRef(Name));
+ if (!ParseAction(std::move(CXXPat)))
+ return false;
+ continue;
+ }
+
+ ::PrintError(DiagLoc,
+ "Failed to parse pattern: '" + Arg->getAsString() + "'");
+ return false;
+ }
+
+ return true;
+}
+
+static const CodeGenInstruction &
+getInstrForIntrinsic(const CodeGenTarget &CGT, const CodeGenIntrinsic *I) {
+ StringRef Opc;
+ if (I->isConvergent) {
+ Opc = I->hasSideEffects ? "G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS"
+ : "G_INTRINSIC_CONVERGENT";
+ } else {
+ Opc = I->hasSideEffects ? "G_INTRINSIC_W_SIDE_EFFECTS" : "G_INTRINSIC";
+ }
+
+ RecordKeeper &RK = I->TheDef->getRecords();
+ return CGT.getInstruction(RK.getDef(Opc));
+}
+
+static const CodeGenIntrinsic *getCodeGenIntrinsic(Record *R) {
+ // Intrinsics need to have a static lifetime because the match table keeps
+ // references to CodeGenIntrinsic objects.
+ static DenseMap<const Record *, std::unique_ptr<CodeGenIntrinsic>>
+ AllIntrinsics;
+
+ auto &Ptr = AllIntrinsics[R];
+ if (!Ptr)
+ Ptr = std::make_unique<CodeGenIntrinsic>(R, std::vector<Record *>());
+ return Ptr.get();
+}
+
+std::unique_ptr<Pattern>
+CombineRuleBuilder::parseInstructionPattern(const Init &Arg,
+ StringRef Name) const {
+ const DagInit *DagPat = dyn_cast<DagInit>(&Arg);
+ if (!DagPat)
+ return nullptr;
+
+ std::unique_ptr<InstructionPattern> Pat;
+ if (const DagInit *IP = getDagWithOperatorOfSubClass(Arg, "Instruction")) {
+ auto &Instr = CGT.getInstruction(IP->getOperatorAsDef(RuleDef.getLoc()));
+ Pat =
+ std::make_unique<CodeGenInstructionPattern>(Instr, insertStrRef(Name));
+ } else if (const DagInit *IP =
+ getDagWithOperatorOfSubClass(Arg, "Intrinsic")) {
+ Record *TheDef = IP->getOperatorAsDef(RuleDef.getLoc());
+ const CodeGenIntrinsic *Intrin = getCodeGenIntrinsic(TheDef);
+ const CodeGenInstruction &Instr = getInstrForIntrinsic(CGT, Intrin);
+ Pat =
+ std::make_unique<CodeGenInstructionPattern>(Instr, insertStrRef(Name));
+ cast<CodeGenInstructionPattern>(*Pat).setIntrinsic(Intrin);
+ } else if (const DagInit *PFP =
+ getDagWithOperatorOfSubClass(Arg, PatFrag::ClassName)) {
+ const Record *Def = PFP->getOperatorAsDef(RuleDef.getLoc());
+ const PatFrag *PF = parsePatFrag(Def);
+ if (!PF)
+ return nullptr; // Already diagnosed by parsePatFrag
+ Pat = std::make_unique<PatFragPattern>(*PF, insertStrRef(Name));
+ } else if (const DagInit *BP =
+ getDagWithOperatorOfSubClass(Arg, BuiltinPattern::ClassName)) {
+ Pat = std::make_unique<BuiltinPattern>(
+ *BP->getOperatorAsDef(RuleDef.getLoc()), insertStrRef(Name));
+ } else
+ return nullptr;
+
+ for (unsigned K = 0; K < DagPat->getNumArgs(); ++K) {
+ Init *Arg = DagPat->getArg(K);
+ if (auto *DagArg = getDagWithSpecificOperator(*Arg, "MIFlags")) {
+ if (!parseInstructionPatternMIFlags(*Pat, DagArg))
+ return nullptr;
+ continue;
+ }
+
+ if (!parseInstructionPatternOperand(*Pat, Arg, DagPat->getArgName(K)))
+ return nullptr;
+ }
+
+ if (!Pat->checkSemantics(RuleDef.getLoc()))
+ return nullptr;
+
+ return std::move(Pat);
+}
+
+std::unique_ptr<Pattern>
+CombineRuleBuilder::parseWipMatchOpcodeMatcher(const Init &Arg,
+ StringRef Name) const {
+ const DagInit *Matcher = getDagWithSpecificOperator(Arg, "wip_match_opcode");
+ if (!Matcher)
+ return nullptr;
+
+ if (Matcher->getNumArgs() == 0) {
+ PrintError("Empty wip_match_opcode");
+ return nullptr;
+ }
+
+ // Each argument is an opcode that can match.
+ auto Result = std::make_unique<AnyOpcodePattern>(insertStrRef(Name));
+ for (const auto &Arg : Matcher->getArgs()) {
+ Record *OpcodeDef = getDefOfSubClass(*Arg, "Instruction");
+ if (OpcodeDef) {
+ Result->addOpcode(&CGT.getInstruction(OpcodeDef));
+ continue;
+ }
+
+ PrintError("Arguments to wip_match_opcode must be instructions");
+ return nullptr;
+ }
+
+ return std::move(Result);
+}
+
+bool CombineRuleBuilder::parseInstructionPatternOperand(
+ InstructionPattern &IP, const Init *OpInit,
+ const StringInit *OpName) const {
+ const auto ParseErr = [&]() {
+ PrintError("cannot parse operand '" + OpInit->getAsUnquotedString() + "' ");
+ if (OpName)
+ PrintNote("operand name is '" + OpName->getAsUnquotedString() + "'");
+ return false;
+ };
+
+ // untyped immediate, e.g. 0
+ if (const auto *IntImm = dyn_cast<IntInit>(OpInit)) {
+ std::string Name = OpName ? OpName->getAsUnquotedString() : "";
+ IP.addOperand(IntImm->getValue(), insertStrRef(Name), PatternType());
+ return true;
+ }
+
+ // typed immediate, e.g. (i32 0)
+ if (const auto *DagOp = dyn_cast<DagInit>(OpInit)) {
+ if (DagOp->getNumArgs() != 1)
+ return ParseErr();
+
+ const Record *TyDef = DagOp->getOperatorAsDef(RuleDef.getLoc());
+ auto ImmTy = PatternType::get(RuleDef.getLoc(), TyDef,
+ "cannot parse immediate '" +
+ DagOp->getAsUnquotedString() + "'");
+ if (!ImmTy)
+ return false;
+
+ if (!IP.hasAllDefs()) {
+ PrintError("out operand of '" + IP.getInstName() +
+ "' cannot be an immediate");
+ return false;
+ }
+
+ const auto *Val = dyn_cast<IntInit>(DagOp->getArg(0));
+ if (!Val)
+ return ParseErr();
+
+ std::string Name = OpName ? OpName->getAsUnquotedString() : "";
+ IP.addOperand(Val->getValue(), insertStrRef(Name), *ImmTy);
+ return true;
+ }
+
+ // Typed operand e.g. $x/$z in (G_FNEG $x, $z)
+ if (auto *DefI = dyn_cast<DefInit>(OpInit)) {
+ if (!OpName) {
+ PrintError("expected an operand name after '" + OpInit->getAsString() +
+ "'");
+ return false;
+ }
+ const Record *Def = DefI->getDef();
+ auto Ty =
+ PatternType::get(RuleDef.getLoc(), Def, "cannot parse operand type");
+ if (!Ty)
+ return false;
+ IP.addOperand(insertStrRef(OpName->getAsUnquotedString()), *Ty);
+ return true;
+ }
+
+ // Untyped operand e.g. $x/$z in (G_FNEG $x, $z)
+ if (isa<UnsetInit>(OpInit)) {
+ assert(OpName && "Unset w/ no OpName?");
+ IP.addOperand(insertStrRef(OpName->getAsUnquotedString()), PatternType());
+ return true;
+ }
+
+ return ParseErr();
+}
+
+bool CombineRuleBuilder::parseInstructionPatternMIFlags(
+ InstructionPattern &IP, const DagInit *Op) const {
+ auto *CGIP = dyn_cast<CodeGenInstructionPattern>(&IP);
+ if (!CGIP) {
+ PrintError("matching/writing MIFlags is only allowed on CodeGenInstruction "
+ "patterns");
+ return false;
+ }
+
+ const auto CheckFlagEnum = [&](const Record *R) {
+ if (!R->isSubClassOf(MIFlagsEnumClassName)) {
+ PrintError("'" + R->getName() + "' is not a subclass of '" +
+ MIFlagsEnumClassName + "'");
+ return false;
+ }
+
+ return true;
+ };
+
+ if (CGIP->getMIFlagsInfo()) {
+ PrintError("MIFlags can only be present once on an instruction");
+ return false;
+ }
+
+ auto &FI = CGIP->getOrCreateMIFlagsInfo();
+ for (unsigned K = 0; K < Op->getNumArgs(); ++K) {
+ const Init *Arg = Op->getArg(K);
+
+ // Match/set a flag: (MIFlags FmNoNans)
+ if (const auto *Def = dyn_cast<DefInit>(Arg)) {
+ const Record *R = Def->getDef();
+ if (!CheckFlagEnum(R))
+ return false;
+
+ FI.addSetFlag(R);
+ continue;
+ }
+
+ // Do not match a flag/unset a flag: (MIFlags (not FmNoNans))
+ if (const DagInit *NotDag = getDagWithSpecificOperator(*Arg, "not")) {
+ for (const Init *NotArg : NotDag->getArgs()) {
+ const DefInit *DefArg = dyn_cast<DefInit>(NotArg);
+ if (!DefArg) {
+ PrintError("cannot parse '" + NotArg->getAsUnquotedString() +
+ "': expected a '" + MIFlagsEnumClassName + "'");
+ return false;
+ }
+
+ const Record *R = DefArg->getDef();
+ if (!CheckFlagEnum(R))
+ return false;
+
+ FI.addUnsetFlag(R);
+ continue;
+ }
+
+ continue;
+ }
+
+ // Copy flags from a matched instruction: (MIFlags $mi)
+ if (isa<UnsetInit>(Arg)) {
+ FI.addCopyFlag(insertStrRef(Op->getArgName(K)->getAsUnquotedString()));
+ continue;
+ }
+ }
+
+ return true;
+}
+
+std::unique_ptr<PatFrag>
+CombineRuleBuilder::parsePatFragImpl(const Record *Def) const {
+ auto StackTrace = PrettyStackTraceParse(*Def);
+ if (!Def->isSubClassOf(PatFrag::ClassName))
+ return nullptr;
+
+ const DagInit *Ins = Def->getValueAsDag("InOperands");
+ if (Ins->getOperatorAsDef(Def->getLoc())->getName() != "ins") {
+ ::PrintError(Def, "expected 'ins' operator for " + PatFrag::ClassName +
+ " in operands list");
+ return nullptr;
+ }
+
+ const DagInit *Outs = Def->getValueAsDag("OutOperands");
+ if (Outs->getOperatorAsDef(Def->getLoc())->getName() != "outs") {
+ ::PrintError(Def, "expected 'outs' operator for " + PatFrag::ClassName +
+ " out operands list");
+ return nullptr;
+ }
+
+ auto Result = std::make_unique<PatFrag>(*Def);
+ if (!parsePatFragParamList(Def->getLoc(), *Outs,
+ [&](StringRef Name, PatFrag::ParamKind Kind) {
+ Result->addOutParam(insertStrRef(Name), Kind);
+ return true;
+ }))
+ return nullptr;
+
+ if (!parsePatFragParamList(Def->getLoc(), *Ins,
+ [&](StringRef Name, PatFrag::ParamKind Kind) {
+ Result->addInParam(insertStrRef(Name), Kind);
+ return true;
+ }))
+ return nullptr;
+
+ const ListInit *Alts = Def->getValueAsListInit("Alternatives");
+ unsigned AltIdx = 0;
+ for (const Init *Alt : *Alts) {
+ const auto *PatDag = dyn_cast<DagInit>(Alt);
+ if (!PatDag) {
+ ::PrintError(Def, "expected dag init for PatFrag pattern alternative");
+ return nullptr;
+ }
+
+ PatFrag::Alternative &A = Result->addAlternative();
+ const auto AddPat = [&](std::unique_ptr<Pattern> Pat) {
+ A.Pats.push_back(std::move(Pat));
+ return true;
+ };
+
+ if (!parsePatternList(
+ *PatDag, AddPat, "pattern", Def->getLoc(),
+ /*AnonPatPrefix*/
+ (Def->getName() + "_alt" + Twine(AltIdx++) + "_pattern").str()))
+ return nullptr;
+ }
+
+ if (!Result->buildOperandsTables() || !Result->checkSemantics())
+ return nullptr;
+
+ return Result;
+}
+
+bool CombineRuleBuilder::parsePatFragParamList(
+ ArrayRef<SMLoc> DiagLoc, const DagInit &OpsList,
+ function_ref<bool(StringRef, PatFrag::ParamKind)> ParseAction) const {
+ for (unsigned K = 0; K < OpsList.getNumArgs(); ++K) {
+ const StringInit *Name = OpsList.getArgName(K);
+ const Init *Ty = OpsList.getArg(K);
+
+ if (!Name) {
+ ::PrintError(DiagLoc, "all operands must be named'");
+ return false;
+ }
+ const std::string NameStr = Name->getAsUnquotedString();
+
+ PatFrag::ParamKind OpKind;
+ if (isSpecificDef(*Ty, "gi_imm"))
+ OpKind = PatFrag::PK_Imm;
+ else if (isSpecificDef(*Ty, "root"))
+ OpKind = PatFrag::PK_Root;
+ else if (isa<UnsetInit>(Ty) ||
+ isSpecificDef(*Ty, "gi_mo")) // no type = gi_mo.
+ OpKind = PatFrag::PK_MachineOperand;
+ else {
+ ::PrintError(
+ DiagLoc,
+ "'" + NameStr +
+ "' operand type was expected to be 'root', 'gi_imm' or 'gi_mo'");
+ return false;
+ }
+
+ if (!ParseAction(NameStr, OpKind))
+ return false;
+ }
+
+ return true;
+}
+
+const PatFrag *CombineRuleBuilder::parsePatFrag(const Record *Def) const {
+ // Cache already parsed PatFrags to avoid doing extra work.
+ static DenseMap<const Record *, std::unique_ptr<PatFrag>> ParsedPatFrags;
+
+ auto It = ParsedPatFrags.find(Def);
+ if (It != ParsedPatFrags.end()) {
+ SeenPatFrags.insert(It->second.get());
+ return It->second.get();
+ }
+
+ std::unique_ptr<PatFrag> NewPatFrag = parsePatFragImpl(Def);
+ if (!NewPatFrag) {
+ ::PrintError(Def, "Could not parse " + PatFrag::ClassName + " '" +
+ Def->getName() + "'");
+ // Put a nullptr in the map so we don't attempt parsing this again.
+ ParsedPatFrags[Def] = nullptr;
+ return nullptr;
+ }
+
+ const auto *Res = NewPatFrag.get();
+ ParsedPatFrags[Def] = std::move(NewPatFrag);
+ SeenPatFrags.insert(Res);
+ return Res;
+}
+
bool CombineRuleBuilder::emitMatchPattern(CodeExpansions &CE,
const PatternAlternatives &Alts,
const InstructionPattern &IP) {
More information about the llvm-commits
mailing list