[llvm] [WIP][TableGen][GISel] Refactor node renderers emission (PR #121071)
Sergei Barannikov via llvm-commits
llvm-commits at lists.llvm.org
Tue Dec 24 21:14:10 PST 2024
https://github.com/s-barannikov updated https://github.com/llvm/llvm-project/pull/121071
>From 1f5bd62e52509bdf6c99832d5d772621b26afd19 Mon Sep 17 00:00:00 2001
From: Sergei Barannikov <barannikov88 at gmail.com>
Date: Wed, 25 Dec 2024 01:16:22 +0300
Subject: [PATCH 1/5] importNamedNodeRenderer
---
llvm/utils/TableGen/GlobalISelEmitter.cpp | 185 ++++++++++++----------
1 file changed, 103 insertions(+), 82 deletions(-)
diff --git a/llvm/utils/TableGen/GlobalISelEmitter.cpp b/llvm/utils/TableGen/GlobalISelEmitter.cpp
index 4250b57581f63e..b98d3427724fc9 100644
--- a/llvm/utils/TableGen/GlobalISelEmitter.cpp
+++ b/llvm/utils/TableGen/GlobalISelEmitter.cpp
@@ -412,6 +412,10 @@ class GlobalISelEmitter final : public GlobalISelMatchTableExecutorEmitter {
importExplicitUseRenderers(action_iterator InsertPt, RuleMatcher &M,
BuildMIAction &DstMIBuilder,
const TreePatternNode &Dst) const;
+
+ Error importNamedNodeRenderer(RuleMatcher &M, BuildMIAction &MIBuilder,
+ const TreePatternNode &N) const;
+
Expected<action_iterator>
importExplicitUseRenderer(action_iterator InsertPt, RuleMatcher &Rule,
BuildMIAction &DstMIBuilder,
@@ -1192,15 +1196,106 @@ Error GlobalISelEmitter::importChildMatcher(
return failedImport("Src pattern child is an unsupported kind");
}
+// Equivalent of MatcherGen::EmitResultOfNamedOperand.
+Error GlobalISelEmitter::importNamedNodeRenderer(
+ RuleMatcher &M, BuildMIAction &MIBuilder, const TreePatternNode &N) const {
+ StringRef NodeName = N.getName();
+
+ if (auto SubOperand = M.getComplexSubOperand(NodeName)) {
+ auto [ComplexPatternRec, RendererID, SubOperandIdx] = *SubOperand;
+ MIBuilder.addRenderer<RenderComplexPatternOperand>(
+ *ComplexPatternRec, NodeName, RendererID, SubOperandIdx);
+ return Error::success();
+ }
+
+ if (!N.isLeaf()) {
+ StringRef OperatorName = N.getOperator()->getName();
+
+ if (OperatorName == "imm") {
+ MIBuilder.addRenderer<CopyConstantAsImmRenderer>(NodeName);
+ return Error::success();
+ }
+
+ if (OperatorName == "fpimm") {
+ MIBuilder.addRenderer<CopyFConstantAsFPImmRenderer>(NodeName);
+ return Error::success();
+ }
+
+ // TODO: 'imm' and 'fpimm' are the only nodes that need special treatment.
+ // Remove this check and add CopyRenderer unconditionally for other nodes.
+ if (OperatorName == "bb" || OperatorName == "timm" ||
+ OperatorName == "tframeindex") {
+ MIBuilder.addRenderer<CopyRenderer>(NodeName);
+ return Error::success();
+ }
+
+ return failedImport("node has unsupported operator " + to_string(N));
+ }
+
+ if (const auto *DI = dyn_cast<DefInit>(N.getLeafValue())) {
+ const Record *R = DI->getDef();
+
+ if (N.getNumResults() != 1)
+ return failedImport("node does not have one result " + to_string(N));
+
+ std::optional<LLTCodeGen> OpTyOrNone;
+ ArrayRef<TypeSetByHwMode> ChildTypes = N.getExtTypes();
+ if (ChildTypes.front().isMachineValueType())
+ OpTyOrNone = MVTToLLT(ChildTypes.front().getMachineValueType().SimpleTy);
+
+ // TODO: Remove this check. Types in the destination DAG should not matter.
+ if (!OpTyOrNone)
+ return failedImport("node has unsupported type " + to_string(N));
+
+ if (R->isSubClassOf("ComplexPattern")) {
+ auto I = ComplexPatternEquivs.find(R);
+ if (I == ComplexPatternEquivs.end())
+ return failedImport("ComplexPattern " + R->getName() +
+ " does not have GISel equivalent");
+
+ const OperandMatcher &OM = M.getOperandMatcher(NodeName);
+ MIBuilder.addRenderer<RenderComplexPatternOperand>(
+ *I->second, NodeName, OM.getAllocatedTemporariesBaseID());
+ return Error::success();
+ }
+
+ if (R->isSubClassOf("RegisterOperand") &&
+ !R->isValueUnset("GIZeroRegister")) {
+ MIBuilder.addRenderer<CopyOrAddZeroRegRenderer>(
+ NodeName, R->getValueAsDef("GIZeroRegister"));
+ return Error::success();
+ }
+
+ // TODO: All special cases are handled above. Remove this check and add
+ // CopyRenderer unconditionally.
+ if (R->isSubClassOf("RegisterClass") ||
+ R->isSubClassOf("RegisterOperand") || R->isSubClassOf("ValueType")) {
+ MIBuilder.addRenderer<CopyRenderer>(NodeName);
+ return Error::success();
+ }
+ }
+
+ // TODO: Change this to assert and move to the beginning of the function.
+ if (!M.hasOperand(NodeName))
+ return failedImport("could not find node $" + NodeName +
+ " in the source DAG");
+
+ // TODO: Remove this check and add CopyRenderer unconditionally.
+ // TODO: Handle nodes with multiple results (provided they can reach here).
+ if (isa<UnsetInit>(N.getLeafValue())) {
+ MIBuilder.addRenderer<CopyRenderer>(NodeName);
+ return Error::success();
+ }
+
+ return failedImport("unsupported node " + to_string(N));
+}
+
Expected<action_iterator> GlobalISelEmitter::importExplicitUseRenderer(
action_iterator InsertPt, RuleMatcher &Rule, BuildMIAction &DstMIBuilder,
const TreePatternNode &Dst) const {
-
- const auto &SubOperand = Rule.getComplexSubOperand(Dst.getName());
- if (SubOperand) {
- DstMIBuilder.addRenderer<RenderComplexPatternOperand>(
- *std::get<0>(*SubOperand), Dst.getName(), std::get<1>(*SubOperand),
- std::get<2>(*SubOperand));
+ if (Dst.hasName()) {
+ if (Error Err = importNamedNodeRenderer(Rule, DstMIBuilder, Dst))
+ return Err;
return InsertPt;
}
@@ -1226,37 +1321,6 @@ Expected<action_iterator> GlobalISelEmitter::importExplicitUseRenderer(
" 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 (Dst.getOperator()->isSubClassOf("SDNode")) {
- auto &ChildSDNI = CGP.getSDNodeInfo(Dst.getOperator());
- if (ChildSDNI.getSDClassName() == "BasicBlockSDNode") {
- DstMIBuilder.addRenderer<CopyRenderer>(Dst.getName());
- return InsertPt;
- }
- }
-
- // Similarly, imm is an operator in TreePatternNode's view but must be
- // rendered as operands.
- // FIXME: The target should be able to choose sign-extended when appropriate
- // (e.g. on Mips).
- if (Dst.getOperator()->getName() == "timm") {
- DstMIBuilder.addRenderer<CopyRenderer>(Dst.getName());
- return InsertPt;
- }
- if (Dst.getOperator()->getName() == "tframeindex") {
- DstMIBuilder.addRenderer<CopyRenderer>(Dst.getName());
- return InsertPt;
- }
- if (Dst.getOperator()->getName() == "imm") {
- DstMIBuilder.addRenderer<CopyConstantAsImmRenderer>(Dst.getName());
- return InsertPt;
- }
- if (Dst.getOperator()->getName() == "fpimm") {
- DstMIBuilder.addRenderer<CopyFConstantAsFPImmRenderer>(Dst.getName());
- return InsertPt;
- }
-
if (Dst.getOperator()->isSubClassOf("Instruction")) {
auto OpTy = getInstResultType(Dst, Target);
if (!OpTy)
@@ -1274,8 +1338,8 @@ Expected<action_iterator> GlobalISelEmitter::importExplicitUseRenderer(
return InsertPtOrError.get();
}
- return failedImport("Dst pattern child isn't a leaf node or an MBB" +
- llvm::to_string(Dst));
+ // Should not reach here.
+ return failedImport("unrecognized node " + llvm::to_string(Dst));
}
// It could be a specific immediate in which case we should just check for
@@ -1289,64 +1353,21 @@ Expected<action_iterator> GlobalISelEmitter::importExplicitUseRenderer(
if (auto *ChildDefInit = dyn_cast<DefInit>(Dst.getLeafValue())) {
auto *ChildRec = ChildDefInit->getDef();
- ArrayRef<TypeSetByHwMode> ChildTypes = Dst.getExtTypes();
- if (ChildTypes.size() != 1)
- return failedImport("Dst pattern child has multiple results");
-
- std::optional<LLTCodeGen> OpTyOrNone;
- if (ChildTypes.front().isMachineValueType())
- OpTyOrNone = MVTToLLT(ChildTypes.front().getMachineValueType().SimpleTy);
- if (!OpTyOrNone)
- return failedImport("Dst operand has an unsupported type");
-
if (ChildRec->isSubClassOf("Register")) {
DstMIBuilder.addRenderer<AddRegisterRenderer>(Target, ChildRec);
return InsertPt;
}
- if (ChildRec->isSubClassOf("RegisterClass") ||
- ChildRec->isSubClassOf("RegisterOperand") ||
- ChildRec->isSubClassOf("ValueType")) {
- if (ChildRec->isSubClassOf("RegisterOperand") &&
- !ChildRec->isValueUnset("GIZeroRegister")) {
- DstMIBuilder.addRenderer<CopyOrAddZeroRegRenderer>(
- Dst.getName(), ChildRec->getValueAsDef("GIZeroRegister"));
- return InsertPt;
- }
-
- DstMIBuilder.addRenderer<CopyRenderer>(Dst.getName());
- return InsertPt;
- }
-
if (ChildRec->isSubClassOf("SubRegIndex")) {
CodeGenSubRegIndex *SubIdx = CGRegs.getSubRegIdx(ChildRec);
DstMIBuilder.addRenderer<ImmRenderer>(SubIdx->EnumValue);
return InsertPt;
}
- if (ChildRec->isSubClassOf("ComplexPattern")) {
- const auto &ComplexPattern = ComplexPatternEquivs.find(ChildRec);
- if (ComplexPattern == ComplexPatternEquivs.end())
- return failedImport(
- "SelectionDAG ComplexPattern not mapped to GlobalISel");
-
- const OperandMatcher &OM = Rule.getOperandMatcher(Dst.getName());
- DstMIBuilder.addRenderer<RenderComplexPatternOperand>(
- *ComplexPattern->second, Dst.getName(),
- OM.getAllocatedTemporariesBaseID());
- return InsertPt;
- }
-
return failedImport(
"Dst pattern child def is an unsupported tablegen class");
}
- // Handle the case where the MVT/register class is omitted in the dest pattern
- // but MVT exists in the source pattern.
- if (isa<UnsetInit>(Dst.getLeafValue()) && Rule.hasOperand(Dst.getName())) {
- DstMIBuilder.addRenderer<CopyRenderer>(Dst.getName());
- return InsertPt;
- }
return failedImport("Dst pattern child is an unsupported kind");
}
>From e01577d8f282b42209158b4d7affd1098969be2d Mon Sep 17 00:00:00 2001
From: Sergei Barannikov <barannikov88 at gmail.com>
Date: Wed, 25 Dec 2024 01:32:05 +0300
Subject: [PATCH 2/5] importLeafNodeRenderer
---
llvm/utils/TableGen/GlobalISelEmitter.cpp | 126 ++++++++++++----------
1 file changed, 67 insertions(+), 59 deletions(-)
diff --git a/llvm/utils/TableGen/GlobalISelEmitter.cpp b/llvm/utils/TableGen/GlobalISelEmitter.cpp
index b98d3427724fc9..ba13a6902e0fd4 100644
--- a/llvm/utils/TableGen/GlobalISelEmitter.cpp
+++ b/llvm/utils/TableGen/GlobalISelEmitter.cpp
@@ -416,6 +416,9 @@ class GlobalISelEmitter final : public GlobalISelMatchTableExecutorEmitter {
Error importNamedNodeRenderer(RuleMatcher &M, BuildMIAction &MIBuilder,
const TreePatternNode &N) const;
+ Error importLeafNodeRenderer(RuleMatcher &M, BuildMIAction &MIBuilder,
+ const TreePatternNode &N) const;
+
Expected<action_iterator>
importExplicitUseRenderer(action_iterator InsertPt, RuleMatcher &Rule,
BuildMIAction &DstMIBuilder,
@@ -1290,85 +1293,90 @@ Error GlobalISelEmitter::importNamedNodeRenderer(
return failedImport("unsupported node " + to_string(N));
}
-Expected<action_iterator> GlobalISelEmitter::importExplicitUseRenderer(
- action_iterator InsertPt, RuleMatcher &Rule, BuildMIAction &DstMIBuilder,
- const TreePatternNode &Dst) const {
- if (Dst.hasName()) {
- if (Error Err = importNamedNodeRenderer(Rule, DstMIBuilder, Dst))
- return Err;
- return InsertPt;
+// Equivalent of MatcherGen::EmitResultLeafAsOperand.
+Error GlobalISelEmitter::importLeafNodeRenderer(
+ RuleMatcher &M, BuildMIAction &MIBuilder, const TreePatternNode &N) const {
+ if (const auto *II = dyn_cast<IntInit>(N.getLeafValue())) {
+ MIBuilder.addRenderer<ImmRenderer>(II->getValue());
+ return Error::success();
}
- if (!Dst.isLeaf()) {
- if (Dst.getOperator()->isSubClassOf("SDNodeXForm")) {
- auto &Child = Dst.getChild(0);
- auto I = SDNodeXFormEquivs.find(Dst.getOperator());
- if (I != SDNodeXFormEquivs.end()) {
- const Record *XFormOpc = Dst.getOperator()->getValueAsDef("Opcode");
- if (XFormOpc->getName() == "timm") {
- // If this is a TargetConstant, there won't be a corresponding
- // instruction to transform. Instead, this will refer directly to an
- // operand in an instruction's operand list.
- DstMIBuilder.addRenderer<CustomOperandRenderer>(*I->second,
- Child.getName());
- } else {
- DstMIBuilder.addRenderer<CustomRenderer>(*I->second, Child.getName());
- }
+ if (const auto *DI = dyn_cast<DefInit>(N.getLeafValue())) {
+ const Record *R = DI->getDef();
- return InsertPt;
- }
- return failedImport("SDNodeXForm " + Child.getName() +
- " has no custom renderer");
+ if (R->isSubClassOf("Register")) {
+ MIBuilder.addRenderer<AddRegisterRenderer>(Target, R);
+ return Error::success();
}
- if (Dst.getOperator()->isSubClassOf("Instruction")) {
- auto OpTy = getInstResultType(Dst, Target);
- if (!OpTy)
- return OpTy.takeError();
+ if (R->isSubClassOf("SubRegIndex")) {
+ const CodeGenSubRegIndex *SubRegIndex = CGRegs.getSubRegIdx(R);
+ MIBuilder.addRenderer<ImmRenderer>(SubRegIndex->EnumValue);
+ return Error::success();
+ }
- unsigned TempRegID = Rule.allocateTempRegID();
- InsertPt =
- Rule.insertAction<MakeTempRegisterAction>(InsertPt, *OpTy, TempRegID);
- DstMIBuilder.addRenderer<TempRegRenderer>(TempRegID);
+ // There are also RegisterClass / RegisterOperand operands of REG_SEQUENCE /
+ // COPY_TO_REGCLASS, but these instructions are currently handled elsewhere.
+ }
- auto InsertPtOrError = createAndImportSubInstructionRenderer(
- ++InsertPt, Rule, Dst, TempRegID);
- if (auto Error = InsertPtOrError.takeError())
- return std::move(Error);
- return InsertPtOrError.get();
- }
+ return failedImport("unrecognized node " + to_string(N));
+}
- // Should not reach here.
- return failedImport("unrecognized node " + llvm::to_string(Dst));
+Expected<action_iterator> GlobalISelEmitter::importExplicitUseRenderer(
+ action_iterator InsertPt, RuleMatcher &Rule, BuildMIAction &DstMIBuilder,
+ const TreePatternNode &Dst) const {
+ if (Dst.hasName()) {
+ if (Error Err = importNamedNodeRenderer(Rule, DstMIBuilder, Dst))
+ return Err;
+ return InsertPt;
}
- // It could be a specific immediate in which case we should just check for
- // that immediate.
- if (const IntInit *ChildIntInit = dyn_cast<IntInit>(Dst.getLeafValue())) {
- DstMIBuilder.addRenderer<ImmRenderer>(ChildIntInit->getValue());
+ if (Dst.isLeaf()) {
+ if (Error Err = importLeafNodeRenderer(Rule, DstMIBuilder, Dst))
+ return Err;
return InsertPt;
}
- // Otherwise, we're looking for a bog-standard RegisterClass operand.
- if (auto *ChildDefInit = dyn_cast<DefInit>(Dst.getLeafValue())) {
- auto *ChildRec = ChildDefInit->getDef();
+ if (Dst.getOperator()->isSubClassOf("SDNodeXForm")) {
+ auto &Child = Dst.getChild(0);
+ auto I = SDNodeXFormEquivs.find(Dst.getOperator());
+ if (I != SDNodeXFormEquivs.end()) {
+ const Record *XFormOpc = Dst.getOperator()->getValueAsDef("Opcode");
+ if (XFormOpc->getName() == "timm") {
+ // If this is a TargetConstant, there won't be a corresponding
+ // instruction to transform. Instead, this will refer directly to an
+ // operand in an instruction's operand list.
+ DstMIBuilder.addRenderer<CustomOperandRenderer>(*I->second,
+ Child.getName());
+ } else {
+ DstMIBuilder.addRenderer<CustomRenderer>(*I->second, Child.getName());
+ }
- if (ChildRec->isSubClassOf("Register")) {
- DstMIBuilder.addRenderer<AddRegisterRenderer>(Target, ChildRec);
return InsertPt;
}
+ return failedImport("SDNodeXForm " + Child.getName() +
+ " has no custom renderer");
+ }
- if (ChildRec->isSubClassOf("SubRegIndex")) {
- CodeGenSubRegIndex *SubIdx = CGRegs.getSubRegIdx(ChildRec);
- DstMIBuilder.addRenderer<ImmRenderer>(SubIdx->EnumValue);
- return InsertPt;
- }
+ if (Dst.getOperator()->isSubClassOf("Instruction")) {
+ auto OpTy = getInstResultType(Dst, Target);
+ if (!OpTy)
+ return OpTy.takeError();
- return failedImport(
- "Dst pattern child def is an unsupported tablegen class");
+ unsigned TempRegID = Rule.allocateTempRegID();
+ InsertPt =
+ Rule.insertAction<MakeTempRegisterAction>(InsertPt, *OpTy, TempRegID);
+ DstMIBuilder.addRenderer<TempRegRenderer>(TempRegID);
+
+ auto InsertPtOrError =
+ createAndImportSubInstructionRenderer(++InsertPt, Rule, Dst, TempRegID);
+ if (auto Error = InsertPtOrError.takeError())
+ return std::move(Error);
+ return InsertPtOrError.get();
}
- return failedImport("Dst pattern child is an unsupported kind");
+ // Should not reach here.
+ return failedImport("unrecognized node " + llvm::to_string(Dst));
}
/// Generates code that builds the resulting instruction(s) from the destination
>From de44234774a419af05dbf92834eb06d073db90bb Mon Sep 17 00:00:00 2001
From: Sergei Barannikov <barannikov88 at gmail.com>
Date: Wed, 25 Dec 2024 01:40:23 +0300
Subject: [PATCH 3/5] importXFormNodeRenderer
---
llvm/utils/TableGen/GlobalISelEmitter.cpp | 59 ++++++++++++++++-------
1 file changed, 41 insertions(+), 18 deletions(-)
diff --git a/llvm/utils/TableGen/GlobalISelEmitter.cpp b/llvm/utils/TableGen/GlobalISelEmitter.cpp
index ba13a6902e0fd4..d5f89770926f3a 100644
--- a/llvm/utils/TableGen/GlobalISelEmitter.cpp
+++ b/llvm/utils/TableGen/GlobalISelEmitter.cpp
@@ -419,6 +419,9 @@ class GlobalISelEmitter final : public GlobalISelMatchTableExecutorEmitter {
Error importLeafNodeRenderer(RuleMatcher &M, BuildMIAction &MIBuilder,
const TreePatternNode &N) const;
+ Error importXFormNodeRenderer(RuleMatcher &M, BuildMIAction &MIBuilder,
+ const TreePatternNode &N) const;
+
Expected<action_iterator>
importExplicitUseRenderer(action_iterator InsertPt, RuleMatcher &Rule,
BuildMIAction &DstMIBuilder,
@@ -1322,6 +1325,41 @@ Error GlobalISelEmitter::importLeafNodeRenderer(
return failedImport("unrecognized node " + to_string(N));
}
+// Equivalent of MatcherGen::EmitResultSDNodeXFormAsOperand.
+Error GlobalISelEmitter::importXFormNodeRenderer(
+ RuleMatcher &M, BuildMIAction &MIBuilder, const TreePatternNode &N) const {
+ const Record *XFormRec = N.getOperator();
+ auto I = SDNodeXFormEquivs.find(XFormRec);
+ if (I == SDNodeXFormEquivs.end())
+ return failedImport("SDNodeXForm " + XFormRec->getName() +
+ " does not have GISel equivalent");
+
+ // TODO: Fail to import if GISDNodeXForm does not have RendererFn.
+ // This currently results in a fatal error in emitRenderOpcodes.
+ const Record *XFormEquivRec = I->second;
+
+ // The node to apply the transformation function to.
+ // FIXME: The node may not have a name and may be a leaf. It should be
+ // rendered first, like any other nodes. This may or may not require
+ // introducing a temporary register, and we can't tell that without
+ // inspecting the node (possibly recursively). This is a general drawback
+ // of appending renderers directly to BuildMIAction.
+ const TreePatternNode &Node = N.getChild(0);
+ StringRef NodeName = Node.getName();
+
+ const Record *XFormOpc = CGP.getSDNodeTransform(XFormRec).first;
+ if (XFormOpc->getName() == "timm") {
+ // If this is a TargetConstant, there won't be a corresponding
+ // instruction to transform. Instead, this will refer directly to an
+ // operand in an instruction's operand list.
+ MIBuilder.addRenderer<CustomOperandRenderer>(*XFormEquivRec, NodeName);
+ } else {
+ MIBuilder.addRenderer<CustomRenderer>(*XFormEquivRec, NodeName);
+ }
+
+ return Error::success();
+}
+
Expected<action_iterator> GlobalISelEmitter::importExplicitUseRenderer(
action_iterator InsertPt, RuleMatcher &Rule, BuildMIAction &DstMIBuilder,
const TreePatternNode &Dst) const {
@@ -1338,24 +1376,9 @@ Expected<action_iterator> GlobalISelEmitter::importExplicitUseRenderer(
}
if (Dst.getOperator()->isSubClassOf("SDNodeXForm")) {
- auto &Child = Dst.getChild(0);
- auto I = SDNodeXFormEquivs.find(Dst.getOperator());
- if (I != SDNodeXFormEquivs.end()) {
- const Record *XFormOpc = Dst.getOperator()->getValueAsDef("Opcode");
- if (XFormOpc->getName() == "timm") {
- // If this is a TargetConstant, there won't be a corresponding
- // instruction to transform. Instead, this will refer directly to an
- // operand in an instruction's operand list.
- DstMIBuilder.addRenderer<CustomOperandRenderer>(*I->second,
- Child.getName());
- } else {
- DstMIBuilder.addRenderer<CustomRenderer>(*I->second, Child.getName());
- }
-
- return InsertPt;
- }
- return failedImport("SDNodeXForm " + Child.getName() +
- " has no custom renderer");
+ if (Error Err = importXFormNodeRenderer(Rule, DstMIBuilder, Dst))
+ return Err;
+ return InsertPt;
}
if (Dst.getOperator()->isSubClassOf("Instruction")) {
>From cb3cc0a4a2fbff17cca1018d1d1658829285668c Mon Sep 17 00:00:00 2001
From: Sergei Barannikov <barannikov88 at gmail.com>
Date: Wed, 25 Dec 2024 01:45:31 +0300
Subject: [PATCH 4/5] importInstructionNodeRenderer
---
llvm/utils/TableGen/GlobalISelEmitter.cpp | 46 ++++++++++++++++-------
1 file changed, 32 insertions(+), 14 deletions(-)
diff --git a/llvm/utils/TableGen/GlobalISelEmitter.cpp b/llvm/utils/TableGen/GlobalISelEmitter.cpp
index d5f89770926f3a..672082502e22c0 100644
--- a/llvm/utils/TableGen/GlobalISelEmitter.cpp
+++ b/llvm/utils/TableGen/GlobalISelEmitter.cpp
@@ -422,6 +422,10 @@ class GlobalISelEmitter final : public GlobalISelMatchTableExecutorEmitter {
Error importXFormNodeRenderer(RuleMatcher &M, BuildMIAction &MIBuilder,
const TreePatternNode &N) const;
+ Error importInstructionNodeRenderer(RuleMatcher &M, BuildMIAction &MIBuilder,
+ const TreePatternNode &N,
+ action_iterator &InsertPt) const;
+
Expected<action_iterator>
importExplicitUseRenderer(action_iterator InsertPt, RuleMatcher &Rule,
BuildMIAction &DstMIBuilder,
@@ -1360,6 +1364,30 @@ Error GlobalISelEmitter::importXFormNodeRenderer(
return Error::success();
}
+// Equivalent of MatcherGen::EmitResultInstructionAsOperand.
+Error GlobalISelEmitter::importInstructionNodeRenderer(
+ RuleMatcher &M, BuildMIAction &MIBuilder, const TreePatternNode &N,
+ action_iterator &InsertPt) const {
+ Expected<LLTCodeGen> OpTy = getInstResultType(N, Target);
+ if (!OpTy)
+ return OpTy.takeError();
+
+ // TODO: See the comment in importXFormNodeRenderer. We rely on the node
+ // requiring a temporary register, which prevents us from using this
+ // function on the root of the destination DAG.
+ unsigned TempRegID = M.allocateTempRegID();
+ InsertPt = M.insertAction<MakeTempRegisterAction>(InsertPt, *OpTy, TempRegID);
+ MIBuilder.addRenderer<TempRegRenderer>(TempRegID);
+
+ auto InsertPtOrError =
+ createAndImportSubInstructionRenderer(++InsertPt, M, N, TempRegID);
+ if (!InsertPtOrError)
+ return InsertPtOrError.takeError();
+
+ InsertPt = *InsertPtOrError;
+ return Error::success();
+}
+
Expected<action_iterator> GlobalISelEmitter::importExplicitUseRenderer(
action_iterator InsertPt, RuleMatcher &Rule, BuildMIAction &DstMIBuilder,
const TreePatternNode &Dst) const {
@@ -1382,20 +1410,10 @@ Expected<action_iterator> GlobalISelEmitter::importExplicitUseRenderer(
}
if (Dst.getOperator()->isSubClassOf("Instruction")) {
- auto OpTy = getInstResultType(Dst, Target);
- if (!OpTy)
- return OpTy.takeError();
-
- unsigned TempRegID = Rule.allocateTempRegID();
- InsertPt =
- Rule.insertAction<MakeTempRegisterAction>(InsertPt, *OpTy, TempRegID);
- DstMIBuilder.addRenderer<TempRegRenderer>(TempRegID);
-
- auto InsertPtOrError =
- createAndImportSubInstructionRenderer(++InsertPt, Rule, Dst, TempRegID);
- if (auto Error = InsertPtOrError.takeError())
- return std::move(Error);
- return InsertPtOrError.get();
+ if (Error Err =
+ importInstructionNodeRenderer(Rule, DstMIBuilder, Dst, InsertPt))
+ return Err;
+ return InsertPt;
}
// Should not reach here.
>From b06dc041bd97decb3213453c77143123fffe571e Mon Sep 17 00:00:00 2001
From: Sergei Barannikov <barannikov88 at gmail.com>
Date: Wed, 25 Dec 2024 01:53:52 +0300
Subject: [PATCH 5/5] Simplify interface
---
llvm/utils/TableGen/GlobalISelEmitter.cpp | 64 +++++++++--------------
1 file changed, 25 insertions(+), 39 deletions(-)
diff --git a/llvm/utils/TableGen/GlobalISelEmitter.cpp b/llvm/utils/TableGen/GlobalISelEmitter.cpp
index 672082502e22c0..8283ad588370ec 100644
--- a/llvm/utils/TableGen/GlobalISelEmitter.cpp
+++ b/llvm/utils/TableGen/GlobalISelEmitter.cpp
@@ -426,10 +426,10 @@ class GlobalISelEmitter final : public GlobalISelMatchTableExecutorEmitter {
const TreePatternNode &N,
action_iterator &InsertPt) const;
- Expected<action_iterator>
- importExplicitUseRenderer(action_iterator InsertPt, RuleMatcher &Rule,
- BuildMIAction &DstMIBuilder,
- const TreePatternNode &Dst) const;
+ Error importNodeRenderer(RuleMatcher &M, BuildMIAction &MIBuilder,
+ const TreePatternNode &N,
+ action_iterator &InsertPt) const;
+
Error importDefaultOperandRenderers(action_iterator InsertPt, RuleMatcher &M,
BuildMIAction &DstMIBuilder,
const DAGDefaultOperand &DefaultOp) const;
@@ -1388,36 +1388,25 @@ Error GlobalISelEmitter::importInstructionNodeRenderer(
return Error::success();
}
-Expected<action_iterator> GlobalISelEmitter::importExplicitUseRenderer(
- action_iterator InsertPt, RuleMatcher &Rule, BuildMIAction &DstMIBuilder,
- const TreePatternNode &Dst) const {
- if (Dst.hasName()) {
- if (Error Err = importNamedNodeRenderer(Rule, DstMIBuilder, Dst))
- return Err;
- return InsertPt;
- }
+// Equivalent of MatcherGen::EmitResultOperand.
+Error GlobalISelEmitter::importNodeRenderer(RuleMatcher &M,
+ BuildMIAction &MIBuilder,
+ const TreePatternNode &N,
+ action_iterator &InsertPt) const {
+ if (N.hasName())
+ return importNamedNodeRenderer(M, MIBuilder, N);
- if (Dst.isLeaf()) {
- if (Error Err = importLeafNodeRenderer(Rule, DstMIBuilder, Dst))
- return Err;
- return InsertPt;
- }
+ if (N.isLeaf())
+ return importLeafNodeRenderer(M, MIBuilder, N);
- if (Dst.getOperator()->isSubClassOf("SDNodeXForm")) {
- if (Error Err = importXFormNodeRenderer(Rule, DstMIBuilder, Dst))
- return Err;
- return InsertPt;
- }
+ if (N.getOperator()->isSubClassOf("SDNodeXForm"))
+ return importXFormNodeRenderer(M, MIBuilder, N);
- if (Dst.getOperator()->isSubClassOf("Instruction")) {
- if (Error Err =
- importInstructionNodeRenderer(Rule, DstMIBuilder, Dst, InsertPt))
- return Err;
- return InsertPt;
- }
+ if (N.getOperator()->isSubClassOf("Instruction"))
+ return importInstructionNodeRenderer(M, MIBuilder, N, InsertPt);
// Should not reach here.
- return failedImport("unrecognized node " + llvm::to_string(Dst));
+ return failedImport("unrecognized node " + llvm::to_string(N));
}
/// Generates code that builds the resulting instruction(s) from the destination
@@ -1671,11 +1660,9 @@ Expected<action_iterator> GlobalISelEmitter::importExplicitUseRenderers(
dyn_cast<DefInit>(SubRegChild.getLeafValue())) {
CodeGenSubRegIndex *SubIdx = CGRegs.getSubRegIdx(SubRegInit->getDef());
- auto InsertPtOrError =
- importExplicitUseRenderer(InsertPt, M, DstMIBuilder, ValChild);
- if (auto Error = InsertPtOrError.takeError())
- return std::move(Error);
- InsertPt = InsertPtOrError.get();
+ if (Error Err = importNodeRenderer(M, DstMIBuilder, ValChild, InsertPt))
+ return Err;
+
DstMIBuilder.addRenderer<SubRegIndexRenderer>(SubIdx);
}
}
@@ -1740,11 +1727,10 @@ Expected<action_iterator> GlobalISelEmitter::importExplicitUseRenderers(
continue;
}
- auto InsertPtOrError = importExplicitUseRenderer(InsertPt, M, DstMIBuilder,
- Dst.getChild(Child));
- if (auto Error = InsertPtOrError.takeError())
- return std::move(Error);
- InsertPt = InsertPtOrError.get();
+ if (Error Err =
+ importNodeRenderer(M, DstMIBuilder, Dst.getChild(Child), InsertPt))
+ return Err;
+
++Child;
}
More information about the llvm-commits
mailing list