From bebaa1737200e4944be71bcab4137a3774c2d07e Mon Sep 17 00:00:00 2001 From: Richard-Qin-X Date: Sun, 16 Aug 2026 20:13:50 +0800 Subject: [RISCV][GlobalISel] Generate shift selections --- backend/lib/TableGen/Parser.cpp | 128 +++++++++++++++++++++++++++++++++++----- 1 file changed, 113 insertions(+), 15 deletions(-) (limited to 'backend/lib/TableGen/Parser.cpp') diff --git a/backend/lib/TableGen/Parser.cpp b/backend/lib/TableGen/Parser.cpp index c194448..b4ff73c 100644 --- a/backend/lib/TableGen/Parser.cpp +++ b/backend/lib/TableGen/Parser.cpp @@ -1231,6 +1231,73 @@ private: return true; } + [[nodiscard]] bool + parseSelectionDefUsePredicates(const yaml::Node &Node, + std::vector &Result) { + if (!requireSequence(&Node, "selection def-use predicates")) + return false; + for (const yaml::NodeID ElementID : Node.sequence()) { + const yaml::Node *Element = Input.node(ElementID); + if (!requireMapping(Element, "selection def-use predicate") || + !checkKeys(*Element, {"operand", "opcode", "captures", "operand_def_constants"}, + "selection def-use predicate")) { + return false; + } + const yaml::Node *OperandNode = + requiredNode(*Element, "operand", "selection def-use predicate"); + const auto Opcode = requiredScalar(*Element, "opcode", "selection def-use predicate"); + if (OperandNode == nullptr || !Opcode) + return false; + const auto Operand = unsignedInteger32(*OperandNode, "selection def-use operand"); + if (!Operand) + return false; + + SourceSelectionDefUsePredicate Predicate{ + .RootOperandIndex = *Operand, + .OpcodeSymbol = *Opcode, + .Captures = {}, + .OperandDefConstants = {}, + .Range = Element->range(), + }; + if (const yaml::Node *Captures = optionalNode(*Element, "captures")) { + if (!requireSequence(Captures, "selection def-use captures")) + return false; + for (const yaml::NodeID CaptureID : Captures->sequence()) { + const yaml::Node *Capture = Input.node(CaptureID); + if (!requireMapping(Capture, "selection def-use capture") || + !checkKeys(*Capture, {"id", "operand"}, "selection def-use capture")) { + return false; + } + const auto Symbol = requiredScalar(*Capture, "id", "selection def-use capture"); + const yaml::Node *CaptureOperand = + requiredNode(*Capture, "operand", "selection def-use capture"); + if (!Symbol || CaptureOperand == nullptr) + return false; + const auto Index = + unsignedInteger32(*CaptureOperand, "selection def-use capture operand"); + if (!Index) + return false; + Predicate.Captures.push_back({ + .Symbol = *Symbol, + .OperandIndex = *Index, + .Range = Capture->range(), + }); + } + } + if (const yaml::Node *Constants = optionalNode(*Element, "operand_def_constants")) { + if (!parseSelectionOperandDefConstants(*Constants, Predicate.OperandDefConstants)) + return false; + } + if (Predicate.Captures.empty() && Predicate.OperandDefConstants.empty()) { + fail(Element->range(), + "selection def-use predicate requires a capture or constant predicate"); + return false; + } + Result.push_back(std::move(Predicate)); + } + return true; + } + [[nodiscard]] bool parseSelectionOperandRenderers(const yaml::Node &Node, std::vector &Result) { @@ -1240,36 +1307,55 @@ private: const yaml::Node *Element = Input.node(ElementID); if (!requireMapping(Element, "selection operand renderer") || !checkKeys(*Element, - {"operand", "physical_register", "temporary", "captured_immediate", - "immediate", "transform", "flags"}, + {"operand", "complex", "physical_register", "temporary", "captured_operand", + "captured_immediate", "immediate", "transform", "flags"}, "selection operand renderer")) { return false; } const yaml::Node *OperandNode = optionalNode(*Element, "operand"); + const yaml::Node *ComplexNode = optionalNode(*Element, "complex"); const yaml::Node *PhysicalRegisterNode = optionalNode(*Element, "physical_register"); const yaml::Node *TemporaryNode = optionalNode(*Element, "temporary"); + const yaml::Node *CapturedOperandNode = optionalNode(*Element, "captured_operand"); const yaml::Node *CapturedImmediateNode = optionalNode(*Element, "captured_immediate"); const yaml::Node *ImmediateNode = optionalNode(*Element, "immediate"); - const std::uint32_t SourceCount = static_cast(OperandNode != nullptr) + - static_cast(PhysicalRegisterNode != nullptr) + - static_cast(TemporaryNode != nullptr) + - static_cast(CapturedImmediateNode != nullptr) + - static_cast(ImmediateNode != nullptr); + const std::uint32_t SourceCount = + static_cast(ComplexNode != nullptr) + + static_cast(ComplexNode == nullptr && OperandNode != nullptr) + + static_cast(PhysicalRegisterNode != nullptr) + + static_cast(TemporaryNode != nullptr) + + static_cast(CapturedOperandNode != nullptr) + + static_cast(CapturedImmediateNode != nullptr) + + static_cast(ImmediateNode != nullptr); if (SourceCount != 1) { fail(Element->range(), "selection operand renderer requires exactly one source"); return false; } SourceSelectionOperandRenderer Renderer{ .OperandIndex = std::nullopt, + .ComplexOperandIndex = std::nullopt, .PhysicalRegisterSymbol = {}, + .ComplexRendererSymbol = {}, .TemporarySymbol = {}, + .CapturedOperandSymbol = {}, .CapturedImmediateOperand = std::nullopt, .Immediate = std::nullopt, .ImmediateTransform = "identity", .Flags = {}, .Range = Element->range(), }; - if (OperandNode != nullptr) { + if (ComplexNode != nullptr) { + if (OperandNode == nullptr) { + fail(Element->range(), "complex selection operand renderer requires an operand index"); + return false; + } + const auto Name = scalar(*ComplexNode, "selection operand renderer complex matcher"); + const auto Index = unsignedInteger32(*OperandNode, "selection operand renderer operand"); + if (!Name || !Index) + return false; + Renderer.ComplexRendererSymbol = *Name; + Renderer.ComplexOperandIndex = Index; + } else if (OperandNode != nullptr) { const auto Index = unsignedInteger32(*OperandNode, "selection operand renderer operand"); if (!Index) return false; @@ -1285,9 +1371,15 @@ private: if (!Symbol) return false; Renderer.TemporarySymbol = *Symbol; + } else if (CapturedOperandNode != nullptr) { + const auto Symbol = + scalar(*CapturedOperandNode, "selection operand renderer captured operand"); + if (!Symbol) + return false; + Renderer.CapturedOperandSymbol = *Symbol; } else if (CapturedImmediateNode != nullptr) { - const auto Index = - unsignedInteger32(*CapturedImmediateNode, "selection operand renderer captured immediate"); + const auto Index = unsignedInteger32(*CapturedImmediateNode, + "selection operand renderer captured immediate"); if (!Index) return false; Renderer.CapturedImmediateOperand = *Index; @@ -1304,7 +1396,8 @@ private: Renderer.ImmediateTransform = *Transform; } if (!Renderer.CapturedImmediateOperand && Renderer.ImmediateTransform != "identity") { - fail(Element->range(), "selection operand renderer transform requires a captured immediate"); + fail(Element->range(), + "selection operand renderer transform requires a captured immediate"); return false; } if (const yaml::Node *FlagsNode = optionalNode(*Element, "flags")) { @@ -1319,7 +1412,7 @@ private: } [[nodiscard]] bool parseSelectionTemporaries(const yaml::Node &Node, - std::vector &Result) { + std::vector &Result) { if (!requireSequence(&Node, "selection temporaries")) return false; for (const yaml::NodeID ElementID : Node.sequence()) { @@ -1329,7 +1422,8 @@ private: return false; } const auto Symbol = requiredScalar(*Element, "id", "selection temporary"); - const yaml::Node *TypeNode = requiredNode(*Element, "type_from_operand", "selection temporary"); + const yaml::Node *TypeNode = + requiredNode(*Element, "type_from_operand", "selection temporary"); if (!Symbol || TypeNode == nullptr) return false; const auto TypeFromOperand = unsignedInteger32(*TypeNode, "selection temporary type operand"); @@ -1345,7 +1439,7 @@ private: } [[nodiscard]] bool parseSelectionActions(const yaml::Node &Node, - std::vector &Result) { + std::vector &Result) { if (!requireSequence(&Node, "selection instructions")) return false; for (const yaml::NodeID ElementID : Node.sequence()) { @@ -1379,7 +1473,7 @@ private: if (!requireMapping(&Node, "selection rule match") || !checkKeys(Node, {"opcode", "result_type", "integer_predicate", "operand_types", "operand_banks", - "operand_classes", "operand_def_constants"}, + "operand_classes", "operand_def_constants", "def_use"}, "selection rule match")) { return false; } @@ -1413,6 +1507,10 @@ private: if (!parseSelectionOperandDefConstants(*OperandDefConstants, Result.OperandDefConstants)) return false; } + if (const yaml::Node *DefUse = optionalNode(Node, "def_use")) { + if (!parseSelectionDefUsePredicates(*DefUse, Result.DefUsePredicates)) + return false; + } return true; } -- cgit v1.2.3