diff options
Diffstat (limited to 'backend/utils/TableGen/GlobalISelEmitter.cpp')
| -rw-r--r-- | backend/utils/TableGen/GlobalISelEmitter.cpp | 233 |
1 files changed, 233 insertions, 0 deletions
diff --git a/backend/utils/TableGen/GlobalISelEmitter.cpp b/backend/utils/TableGen/GlobalISelEmitter.cpp new file mode 100644 index 0000000..3ce9411 --- /dev/null +++ b/backend/utils/TableGen/GlobalISelEmitter.cpp @@ -0,0 +1,233 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "TableGenBackends.h" + +#include <cstddef> +#include <cstdint> +#include <ostream> +#include <sstream> +#include <string> +#include <string_view> + +namespace rcc::targetgen { +namespace { + +[[nodiscard]] std::string_view typeKindName(NormalizedSelectionTypeKind Kind) noexcept { + switch (Kind) { + case NormalizedSelectionTypeKind::Any: + return "Any"; + case NormalizedSelectionTypeKind::Scalar: + return "Scalar"; + case NormalizedSelectionTypeKind::Pointer: + return "Pointer"; + } + return "Any"; +} + +void emitInstruction(std::ostream &Output, std::string_view Opcode, std::uint32_t OperandIndex, + std::uint32_t Value = 0, std::string_view Auxiliary = "0", + std::int64_t Immediate = 0, std::string_view Symbol = {}) { + Output << " {GIMatchTableOpcode::" << Opcode << ", " << OperandIndex << ", " << Value << ", " + << Auxiliary << ", " << Immediate << ", "; + appendQuoted(Output, Symbol); + Output << "},\n"; +} + +void emitTypePredicate(std::ostream &Output, std::uint32_t OperandIndex, + const NormalizedSelectionTypePredicate &Predicate) { + emitInstruction(Output, "CheckOperandType", OperandIndex, Predicate.Bits, + "static_cast<std::uint32_t>(GIMatchTypeKind::" + + std::string(typeKindName(Predicate.Kind)) + ")"); +} + +[[nodiscard]] std::size_t instructionCount(const NormalizedSelectionRule &Rule) noexcept { + std::size_t Count = 2U + (Rule.ResultType ? 1U : 0U) + (Rule.IntegerPredicate ? 1U : 0U) + + (Rule.FloatingPredicate ? 1U : 0U) + (Rule.MemoryPredicate ? 1U : 0U) + + Rule.TargetPredicates.size() + Rule.OperandTypes.size() + + Rule.OperandBanks.size() + Rule.OperandClasses.size() + + Rule.OperandImmediates.size() + Rule.OperandDefConstants.size() + + Rule.Temporaries.size() + Rule.EraseOperandDefinitions.size(); + for (const NormalizedSelectionDefUsePredicate &Predicate : Rule.DefUsePredicates) + Count += 1U + static_cast<std::size_t>(Predicate.IntegerPredicate.has_value()) + + Predicate.Captures.size() + Predicate.OperandDefConstants.size(); + for (const NormalizedSelectionAction &Action : Rule.Actions) + Count += 1U + Action.OperandRenderers.size(); + return Count; +} + +} // namespace + +std::string emitGlobalISel(const NormalizedTargetModel &Model, std::string_view SourceName) { + std::size_t InstructionCount = 0; + std::size_t ConstantRangeCount = 0; + for (const NormalizedSelectionRule &Rule : Model.SelectionRules) + InstructionCount += instructionCount(Rule); + for (const NormalizedSelectionRule &Rule : Model.SelectionRules) { + for (const NormalizedSelectionOperandImmediatePredicate &Predicate : Rule.OperandImmediates) { + ConstantRangeCount += Predicate.Ranges.size(); + } + for (const NormalizedSelectionOperandDefConstantPredicate &Predicate : + Rule.OperandDefConstants) { + ConstantRangeCount += Predicate.Ranges.size(); + } + for (const NormalizedSelectionDefUsePredicate &DefUse : Rule.DefUsePredicates) { + for (const NormalizedSelectionOperandDefConstantPredicate &Predicate : + DefUse.OperandDefConstants) { + ConstantRangeCount += Predicate.Ranges.size(); + } + } + } + + std::ostringstream Output; + Output << "// SPDX-License-Identifier: GPL-3.0-or-later\n\n"; + Output << "// This file is generated by rcc-tblgen from "; + appendQuoted(Output, SourceName); + Output << ". Do not edit it manually.\n\n"; + Output << "#ifdef GET_GLOBALISEL_MATCH_TABLE\n\n"; + Output << "constexpr std::array<GIMatchTableConstantRange, " << ConstantRangeCount + << "> GeneratedGlobalISelConstantRanges = {{\n"; + for (const NormalizedSelectionRule &Rule : Model.SelectionRules) { + for (const NormalizedSelectionOperandImmediatePredicate &Predicate : Rule.OperandImmediates) { + for (const NormalizedSelectionConstantRange &Range : Predicate.Ranges) + Output << " {" << Range.Minimum << ", " << Range.Maximum << "},\n"; + } + for (const NormalizedSelectionOperandDefConstantPredicate &Predicate : + Rule.OperandDefConstants) { + for (const NormalizedSelectionConstantRange &Range : Predicate.Ranges) + Output << " {" << Range.Minimum << ", " << Range.Maximum << "},\n"; + } + for (const NormalizedSelectionDefUsePredicate &DefUse : Rule.DefUsePredicates) { + for (const NormalizedSelectionOperandDefConstantPredicate &Predicate : + DefUse.OperandDefConstants) { + for (const NormalizedSelectionConstantRange &Range : Predicate.Ranges) + Output << " {" << Range.Minimum << ", " << Range.Maximum << "},\n"; + } + } + } + Output << "}};\n\n"; + + Output << "constexpr std::array<GIMatchTableInstruction, " << InstructionCount + << "> GeneratedGlobalISelInstructions = {{\n"; + std::size_t FirstConstantRange = 0; + for (const NormalizedSelectionRule &Rule : Model.SelectionRules) { + emitInstruction(Output, "CheckOpcode", 0, Rule.MatchOpcode); + if (Rule.ResultType) + emitTypePredicate(Output, 0, *Rule.ResultType); + if (Rule.IntegerPredicate) + emitInstruction(Output, "CheckIntegerPredicate", Rule.IntegerPredicate->OperandIndex, + Rule.IntegerPredicate->Predicate); + if (Rule.FloatingPredicate) + emitInstruction(Output, "CheckFloatingPredicate", Rule.FloatingPredicate->OperandIndex, + Rule.FloatingPredicate->Predicate); + if (Rule.MemoryPredicate) + emitInstruction(Output, "CheckMemorySize", Rule.MemoryPredicate->MemoryOperandIndex, + Rule.MemoryPredicate->Bytes); + for (const std::string &Predicate : Rule.TargetPredicates) + emitInstruction(Output, "CheckTargetPredicate", 0, 0, "0", 0, Predicate); + for (const NormalizedSelectionOperandTypePredicate &Predicate : Rule.OperandTypes) + emitTypePredicate(Output, Predicate.OperandIndex, Predicate.Type); + for (const NormalizedSelectionOperandBankPredicate &Predicate : Rule.OperandBanks) + emitInstruction(Output, "CheckOperandBank", Predicate.OperandIndex, Predicate.Bank); + for (const NormalizedSelectionOperandClassPredicate &Predicate : Rule.OperandClasses) + emitInstruction(Output, "CheckOperandClass", Predicate.OperandIndex, Predicate.RegClass); + for (const NormalizedSelectionOperandImmediatePredicate &Predicate : Rule.OperandImmediates) { + emitInstruction(Output, "CheckOperandImmediateRanges", Predicate.OperandIndex, + static_cast<std::uint32_t>(FirstConstantRange), + std::to_string(Predicate.Ranges.size())); + FirstConstantRange += Predicate.Ranges.size(); + } + for (const NormalizedSelectionOperandDefConstantPredicate &Predicate : + Rule.OperandDefConstants) { + emitInstruction(Output, "CheckOperandDefConstantRanges", Predicate.OperandIndex, + static_cast<std::uint32_t>(FirstConstantRange), + std::to_string(Predicate.Ranges.size())); + FirstConstantRange += Predicate.Ranges.size(); + } + for (const NormalizedSelectionDefUsePredicate &DefUse : Rule.DefUsePredicates) { + emitInstruction(Output, "CheckOperandDefOpcode", DefUse.RootOperandIndex, DefUse.Opcode); + if (DefUse.IntegerPredicate) { + emitInstruction(Output, "CheckOperandDefIntegerPredicate", DefUse.RootOperandIndex, + DefUse.IntegerPredicate->Predicate, + std::to_string(DefUse.IntegerPredicate->OperandIndex)); + } + for (const NormalizedSelectionOperandDefConstantPredicate &Predicate : + DefUse.OperandDefConstants) { + emitInstruction(Output, "CheckOperandDefOperandConstantRanges", DefUse.RootOperandIndex, + static_cast<std::uint32_t>(FirstConstantRange), + std::to_string(Predicate.OperandIndex), + static_cast<std::int64_t>(Predicate.Ranges.size())); + FirstConstantRange += Predicate.Ranges.size(); + } + for (const NormalizedSelectionDefUseCapture &Capture : DefUse.Captures) + emitInstruction(Output, "CaptureDefOperand", DefUse.RootOperandIndex, Capture.ID, + std::to_string(Capture.OperandIndex)); + } + for (const NormalizedSelectionTemporary &Temporary : Rule.Temporaries) { + if (Temporary.TypeFromOperand) { + emitInstruction(Output, "CreateTemporary", *Temporary.TypeFromOperand, Temporary.ID); + continue; + } + emitInstruction(Output, "CreateTemporaryType", 0, Temporary.ID, + "static_cast<std::uint32_t>(GIMatchTypeKind::" + + std::string(typeKindName(Temporary.Type->Kind)) + ")", + Temporary.Type->Bits); + } + for (const NormalizedSelectionAction &Action : Rule.Actions) { + emitInstruction(Output, Action.ReplacesRoot ? "MutateOpcode" : "BuildInstruction", 0, + Action.ResultOpcode); + for (const NormalizedSelectionOperandRenderer &Renderer : Action.OperandRenderers) { + switch (Renderer.SourceKind) { + case NormalizedSelectionOperandRenderer::Kind::Operand: + emitInstruction(Output, "RenderOperand", Renderer.Value); + break; + case NormalizedSelectionOperandRenderer::Kind::ComplexOperand: + emitInstruction(Output, "RenderComplexOperand", Renderer.Value, 0, "0", 0, + Renderer.ComplexRenderer); + break; + case NormalizedSelectionOperandRenderer::Kind::PhysicalRegister: + emitInstruction(Output, "RenderPhysicalRegister", 0, Renderer.Value, + std::to_string(Renderer.Flags)); + break; + case NormalizedSelectionOperandRenderer::Kind::Temporary: + emitInstruction(Output, "RenderTemporary", 0, Renderer.Value, + std::to_string(Renderer.Flags)); + break; + case NormalizedSelectionOperandRenderer::Kind::CapturedOperand: + emitInstruction(Output, "RenderCapturedOperand", 0, Renderer.Value); + break; + case NormalizedSelectionOperandRenderer::Kind::CapturedImmediate: + emitInstruction(Output, "RenderCapturedImmediate", Renderer.Value, + static_cast<std::uint32_t>(Renderer.Transform)); + break; + case NormalizedSelectionOperandRenderer::Kind::Immediate: + emitInstruction(Output, "RenderImmediate", 0, 0, "0", Renderer.Immediate); + break; + } + } + } + for (const std::uint32_t OperandIndex : Rule.EraseOperandDefinitions) + emitInstruction(Output, "EraseOperandDefinition", OperandIndex); + emitInstruction(Output, "Complete", 0); + } + Output << "}};\n\n"; + + Output << "constexpr std::array<GIMatchTableRule, " << Model.SelectionRules.size() + << "> GeneratedGlobalISelRules = {{\n"; + std::size_t FirstInstruction = 0; + for (const NormalizedSelectionRule &Rule : Model.SelectionRules) { + const std::size_t Count = instructionCount(Rule); + Output << " {"; + appendQuoted(Output, Rule.Symbol); + Output << ", " << Rule.Priority << ", " << FirstInstruction << ", " << Count << "},\n"; + FirstInstruction += Count; + } + Output << "}};\n\n"; + Output << "[[nodiscard]] constexpr GIMatchTable generatedGlobalISelMatchTable() noexcept {\n" + " return {GeneratedGlobalISelInstructions, GeneratedGlobalISelRules,\n" + " GeneratedGlobalISelConstantRanges};\n" + "}\n\n"; + Output << "#endif // GET_GLOBALISEL_MATCH_TABLE\n"; + return Output.str(); +} + +} // namespace rcc::targetgen |
