summaryrefslogtreecommitdiffstats
path: root/llvm/utils/TableGen
diff options
context:
space:
mode:
authorVolkan Keles <vkeles@apple.com>2018-01-16 18:44:05 +0000
committerVolkan Keles <vkeles@apple.com>2018-01-16 18:44:05 +0000
commitf7f2568613025e120c406da4f9f95a323f477024 (patch)
treea79099f2323f99327a85c48f258c020e5cd2e262 /llvm/utils/TableGen
parenta0db63a195de29e6e9e43293fe6c3d977c82b3b9 (diff)
downloadbcm5719-llvm-f7f2568613025e120c406da4f9f95a323f477024.tar.gz
bcm5719-llvm-f7f2568613025e120c406da4f9f95a323f477024.zip
[GlobalISel][TableGen] Add support for SDNodeXForm
Summary: This patch adds CustomRenderer which renders the matched operands to the specified instruction. Targets can enable the matching of SDNodeXForm by adding a definition that inherits from GICustomOperandRenderer and GISDNodeXFormEquiv as follows. def gi_imm8 : GICustomOperandRenderer<"renderImm8”>, GISDNodeXFormEquiv<imm8_xform>; Custom renderer functions should be of the form: void render(MachineInstrBuilder &MIB, const MachineInstr &I); Reviewers: dsanders, ab, rovka Reviewed By: dsanders Subscribers: kristof.beyls, javed.absar, llvm-commits, mgrang, qcolombet Differential Revision: https://reviews.llvm.org/D42012 llvm-svn: 322582
Diffstat (limited to 'llvm/utils/TableGen')
-rw-r--r--llvm/utils/TableGen/GlobalISelEmitter.cpp132
1 files changed, 106 insertions, 26 deletions
diff --git a/llvm/utils/TableGen/GlobalISelEmitter.cpp b/llvm/utils/TableGen/GlobalISelEmitter.cpp
index c7d662db5a2..b4073b15daa 100644
--- a/llvm/utils/TableGen/GlobalISelEmitter.cpp
+++ b/llvm/utils/TableGen/GlobalISelEmitter.cpp
@@ -260,6 +260,11 @@ std::string explainOperator(Record *Operator) {
")")
.str();
+ if (Operator->isSubClassOf("SDNodeXForm"))
+ return (" (Operator is an unmapped SDNodeXForm, " + Operator->getName() +
+ ")")
+ .str();
+
return (" (Operator " + Operator->getName() + " not understood)").str();
}
@@ -315,12 +320,7 @@ static Error isTrivialOperatorNode(const TreePatternNode *N) {
break;
}
- if (N->getTransformFn()) {
- Explanation += Separator + "Has a transform function";
- Separator = ", ";
- }
-
- if (!HasUnsupportedPredicate && !N->getTransformFn())
+ if (!HasUnsupportedPredicate)
return Error::success();
return failedImport(Explanation);
@@ -1706,7 +1706,8 @@ public:
OR_Imm,
OR_Register,
OR_TempRegister,
- OR_ComplexPattern
+ OR_ComplexPattern,
+ OR_Custom
};
protected:
@@ -2018,6 +2019,38 @@ public:
}
};
+class CustomRenderer : public OperandRenderer {
+protected:
+ unsigned InsnID;
+ const Record &Renderer;
+ /// The name of the operand.
+ const std::string SymbolicName;
+
+public:
+ CustomRenderer(unsigned InsnID, const Record &Renderer,
+ StringRef SymbolicName)
+ : OperandRenderer(OR_Custom), InsnID(InsnID), Renderer(Renderer),
+ SymbolicName(SymbolicName) {}
+
+ static bool classof(const OperandRenderer *R) {
+ return R->getKind() == OR_Custom;
+ }
+
+ void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override {
+ const InstructionMatcher &InsnMatcher =
+ Rule.getInstructionMatcher(SymbolicName);
+ unsigned OldInsnVarID = Rule.getInsnVarID(InsnMatcher);
+ Table << MatchTable::Opcode("GIR_CustomRenderer")
+ << MatchTable::Comment("InsnID") << MatchTable::IntValue(InsnID)
+ << MatchTable::Comment("OldInsnID")
+ << MatchTable::IntValue(OldInsnVarID)
+ << MatchTable::Comment("Renderer")
+ << MatchTable::NamedValue(
+ "GICR_" + Renderer.getValueAsString("RendererFn").str())
+ << MatchTable::Comment(SymbolicName) << MatchTable::LineBreak;
+ }
+};
+
/// An action taken when all Matcher predicates succeeded for a parent rule.
///
/// Typical actions include:
@@ -2541,6 +2574,11 @@ private:
/// GIComplexPatternEquiv.
DenseMap<const Record *, const Record *> ComplexPatternEquivs;
+ /// Keep track of the equivalence between SDNodeXForm's and
+ /// GICustomOperandRenderer. Map entries are specified by subclassing
+ /// GISDNodeXFormEquiv.
+ DenseMap<const Record *, const Record *> SDNodeXFormEquivs;
+
// Map of predicates to their subtarget features.
SubtargetFeatureInfoMap SubtargetFeatures;
@@ -2645,6 +2683,14 @@ void GlobalISelEmitter::gatherNodeEquivs() {
continue;
ComplexPatternEquivs[SelDAGEquiv] = Equiv;
}
+
+ assert(SDNodeXFormEquivs.empty());
+ for (Record *Equiv : RK.getAllDerivedDefinitions("GISDNodeXFormEquiv")) {
+ Record *SelDAGEquiv = Equiv->getValueAsDef("SelDAGEquivalent");
+ if (!SelDAGEquiv)
+ continue;
+ SDNodeXFormEquivs[SelDAGEquiv] = Equiv;
+ }
}
Record *GlobalISelEmitter::findNodeEquiv(Record *N) const {
@@ -2986,10 +3032,6 @@ Error GlobalISelEmitter::importChildMatcher(RuleMatcher &Rule,
Expected<action_iterator> GlobalISelEmitter::importExplicitUseRenderer(
action_iterator InsertPt, RuleMatcher &Rule, BuildMIAction &DstMIBuilder,
TreePatternNode *DstChild) {
- if (DstChild->getTransformFn() != nullptr) {
- return failedImport("Dst pattern child has transform fn " +
- DstChild->getTransformFn()->getName());
- }
const auto &SubOperand = Rule.getComplexSubOperand(DstChild->getName());
if (SubOperand.hasValue()) {
@@ -3000,6 +3042,18 @@ Expected<action_iterator> GlobalISelEmitter::importExplicitUseRenderer(
}
if (!DstChild->isLeaf()) {
+
+ if (DstChild->getOperator()->isSubClassOf("SDNodeXForm")) {
+ auto Child = DstChild->getChild(0);
+ auto I = SDNodeXFormEquivs.find(DstChild->getOperator());
+ if (I != SDNodeXFormEquivs.end()) {
+ DstMIBuilder.addRenderer<CustomRenderer>(*I->second, Child->getName());
+ return InsertPt;
+ }
+ return failedImport("SDNodeXForm " + Child->getName() +
+ " has no custom renderer");
+ }
+
// We accept 'bb' here. It's an operator because BasicBlockSDNode isn't
// inline, but in MI it's just another operand.
if (DstChild->getOperator()->isSubClassOf("SDNode")) {
@@ -3104,10 +3158,6 @@ Expected<action_iterator> GlobalISelEmitter::importExplicitUseRenderer(
return InsertPt;
}
- if (ChildRec->isSubClassOf("SDNodeXForm"))
- return failedImport("Dst pattern child def is an unsupported tablegen "
- "class (SDNodeXForm)");
-
return failedImport(
"Dst pattern child def is an unsupported tablegen class");
}
@@ -3652,14 +3702,19 @@ void GlobalISelEmitter::run(raw_ostream &OS) {
Rules.push_back(std::move(MatcherOrErr.get()));
}
+ // Comparison function to order records by name.
+ auto orderByName = [](const Record *A, const Record *B) {
+ return A->getName() < B->getName();
+ };
+
std::vector<Record *> ComplexPredicates =
RK.getAllDerivedDefinitions("GIComplexOperandMatcher");
- std::sort(ComplexPredicates.begin(), ComplexPredicates.end(),
- [](const Record *A, const Record *B) {
- if (A->getName() < B->getName())
- return true;
- return false;
- });
+ std::sort(ComplexPredicates.begin(), ComplexPredicates.end(), orderByName);
+
+ std::vector<Record *> CustomRendererFns =
+ RK.getAllDerivedDefinitions("GICustomOperandRenderer");
+ std::sort(CustomRendererFns.begin(), CustomRendererFns.end(), orderByName);
+
unsigned MaxTemporaries = 0;
for (const auto &Rule : Rules)
MaxTemporaries = std::max(MaxTemporaries, Rule.countRendererFns());
@@ -3677,10 +3732,18 @@ void GlobalISelEmitter::run(raw_ostream &OS) {
"ComplexRendererFns("
<< Target.getName()
<< "InstructionSelector::*ComplexMatcherMemFn)(MachineOperand &) const;\n"
- << " const MatcherInfoTy<PredicateBitset, ComplexMatcherMemFn> "
- "MatcherInfo;\n"
- << " static " << Target.getName()
+
+ << " typedef void(" << Target.getName()
+ << "InstructionSelector::*CustomRendererFn)(MachineInstrBuilder &, const "
+ "MachineInstr&) "
+ "const;\n"
+ << " const ISelInfoTy<PredicateBitset, ComplexMatcherMemFn, "
+ "CustomRendererFn> "
+ "ISelInfo;\n";
+ OS << " static " << Target.getName()
<< "InstructionSelector::ComplexMatcherMemFn ComplexPredicateFns[];\n"
+ << " static " << Target.getName()
+ << "InstructionSelector::CustomRendererFn CustomRenderers[];\n"
<< "bool testImmPredicate_I64(unsigned PredicateID, int64_t Imm) const "
"override;\n"
<< "bool testImmPredicate_APInt(unsigned PredicateID, const APInt &Imm) "
@@ -3691,7 +3754,8 @@ void GlobalISelEmitter::run(raw_ostream &OS) {
OS << "#ifdef GET_GLOBALISEL_TEMPORARIES_INIT\n"
<< ", State(" << MaxTemporaries << "),\n"
- << "MatcherInfo({TypeObjects, FeatureBitsets, ComplexPredicateFns})\n"
+ << "ISelInfo({TypeObjects, FeatureBitsets, ComplexPredicateFns, "
+ "CustomRenderers})\n"
<< "#endif // ifdef GET_GLOBALISEL_TEMPORARIES_INIT\n\n";
OS << "#ifdef GET_GLOBALISEL_IMPL\n";
@@ -3821,6 +3885,22 @@ void GlobalISelEmitter::run(raw_ostream &OS) {
<< ", // " << Record->getName() << "\n";
OS << "};\n\n";
+ OS << "// Custom renderers.\n"
+ << "enum {\n"
+ << " GICR_Invalid,\n";
+ for (const auto &Record : CustomRendererFns)
+ OS << " GICR_" << Record->getValueAsString("RendererFn") << ", \n";
+ OS << "};\n";
+
+ OS << Target.getName() << "InstructionSelector::CustomRendererFn\n"
+ << Target.getName() << "InstructionSelector::CustomRenderers[] = {\n"
+ << " nullptr, // GICP_Invalid\n";
+ for (const auto &Record : CustomRendererFns)
+ OS << " &" << Target.getName()
+ << "InstructionSelector::" << Record->getValueAsString("RendererFn")
+ << ", // " << Record->getName() << "\n";
+ OS << "};\n\n";
+
OS << "bool " << Target.getName()
<< "InstructionSelector::selectImpl(MachineInstr &I, CodeGenCoverage "
"&CoverageInfo) const {\n"
@@ -3862,7 +3942,7 @@ void GlobalISelEmitter::run(raw_ostream &OS) {
}
Table << MatchTable::Opcode("GIM_Reject") << MatchTable::LineBreak;
Table.emitDeclaration(OS);
- OS << " if (executeMatchTable(*this, OutMIs, State, MatcherInfo, ";
+ OS << " if (executeMatchTable(*this, OutMIs, State, ISelInfo, ";
Table.emitUse(OS);
OS << ", TII, MRI, TRI, RBI, AvailableFeatures, CoverageInfo)) {\n"
<< " return true;\n"
OpenPOWER on IntegriCloud