aboutsummaryrefslogtreecommitdiff
path: root/backend/utils/TableGen/MacroFusionEmitter.cpp
diff options
context:
space:
mode:
authorRichard-Qin-X <richard.qin.001@gmail.com>2026-08-22 18:49:08 +0800
committerRichard-Qin-X <richard.qin.001@gmail.com>2026-08-22 18:49:08 +0800
commit8a4bb6e3b0bffa0ed79b51347b12ee4293b622a7 (patch)
tree51278f18d8954e7abb5820cb9d529e3d5e5f322b /backend/utils/TableGen/MacroFusionEmitter.cpp
parent9ca9fb23124e8c5d714e9668210855a23dd2a72f (diff)
downloadrcc-project-8a4bb6e3b0bffa0ed79b51347b12ee4293b622a7.tar.gz
rcc-project-8a4bb6e3b0bffa0ed79b51347b12ee4293b622a7.tar.xz
[CodeGen] Generate RISC-V macro fusion rules
Diffstat (limited to 'backend/utils/TableGen/MacroFusionEmitter.cpp')
-rw-r--r--backend/utils/TableGen/MacroFusionEmitter.cpp100
1 files changed, 100 insertions, 0 deletions
diff --git a/backend/utils/TableGen/MacroFusionEmitter.cpp b/backend/utils/TableGen/MacroFusionEmitter.cpp
new file mode 100644
index 0000000..2018a43
--- /dev/null
+++ b/backend/utils/TableGen/MacroFusionEmitter.cpp
@@ -0,0 +1,100 @@
+// 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
+instructionSide(NormalizedMacroFusionInstruction Instruction) noexcept {
+ return Instruction == NormalizedMacroFusionInstruction::First ? "First" : "Second";
+}
+
+void emitOpcodes(std::ostream &Output, const NormalizedMacroFusionRule &Rule,
+ std::string_view Suffix, const std::vector<std::uint32_t> &Opcodes) {
+ Output << "constexpr std::array<Opcode, " << Opcodes.size() << "> " << Rule.Symbol << Suffix
+ << " = {{\n";
+ for (const std::uint32_t Opcode : Opcodes)
+ Output << " Opcode::fromValue(" << Opcode << "),\n";
+ Output << "}};\n";
+}
+
+} // namespace
+
+std::string emitMacroFusion(const NormalizedTargetModel &Model, std::string_view SourceName) {
+ 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_MACRO_FUSION_RULES\n\n";
+ for (const NormalizedMacroFusionRule &Rule : Model.MacroFusionRules) {
+ emitOpcodes(Output, Rule, "FirstOpcodes", Rule.FirstOpcodes);
+ emitOpcodes(Output, Rule, "SecondOpcodes", Rule.SecondOpcodes);
+ Output << "constexpr std::array<MacroFusionOpcodePair, " << Rule.OpcodePairs.size() << "> "
+ << Rule.Symbol << "OpcodePairs = {{\n";
+ for (const NormalizedMacroFusionOpcodePair &Pair : Rule.OpcodePairs) {
+ Output << " {Opcode::fromValue(" << Pair.FirstOpcode << "), Opcode::fromValue("
+ << Pair.SecondOpcode << ")},\n";
+ }
+ Output << "}};\n";
+ Output << "constexpr std::array<MacroFusionImmediatePredicate, "
+ << Rule.ImmediatePredicates.size() << "> " << Rule.Symbol
+ << "ImmediatePredicates = {{\n";
+ for (const NormalizedMacroFusionImmediatePredicate &Predicate : Rule.ImmediatePredicates) {
+ Output << " {MacroFusionInstruction::" << instructionSide(Predicate.Instruction) << ", "
+ << Predicate.OperandIndex << ", " << Predicate.Minimum << ", " << Predicate.Maximum
+ << "},\n";
+ }
+ Output << "}};\n";
+ Output << "constexpr std::array<MacroFusionRegisterInequality, "
+ << Rule.RegisterInequalities.size() << "> " << Rule.Symbol
+ << "RegisterInequalities = {{\n";
+ for (const NormalizedMacroFusionRegisterInequality &Predicate : Rule.RegisterInequalities) {
+ Output << " {MacroFusionInstruction::" << instructionSide(Predicate.Instruction) << ", "
+ << Predicate.LeftOperand << ", " << Predicate.RightOperand << "},\n";
+ }
+ Output << "}};\n";
+ Output << "constexpr std::array<MacroFusionImmediateRelation, "
+ << Rule.ImmediateRelations.size() << "> " << Rule.Symbol << "ImmediateRelations = {{\n";
+ for (const NormalizedMacroFusionImmediateRelation &Relation : Rule.ImmediateRelations)
+ Output << " {" << Relation.FirstOperand << ", " << Relation.SecondOperand << "},\n";
+ Output << "}};\n\n";
+ }
+
+ Output << "constexpr std::array<MacroFusionRule, " << Model.MacroFusionRules.size()
+ << "> GeneratedMacroFusionRules = {{\n";
+ for (const NormalizedMacroFusionRule &Rule : Model.MacroFusionRules) {
+ Output << " {";
+ appendQuoted(Output, Rule.Symbol);
+ Output << ", ";
+ appendQuoted(Output, Rule.Feature);
+ Output << ", " << Rule.Symbol << "FirstOpcodes, " << Rule.Symbol << "SecondOpcodes, "
+ << Rule.Symbol << "OpcodePairs, " << Rule.Symbol << "ImmediatePredicates, "
+ << Rule.Symbol << "RegisterInequalities, " << Rule.Symbol << "ImmediateRelations, "
+ << Rule.FirstDefinitionOperand << ", " << Rule.SecondUseOperand << ", "
+ << Rule.SecondDefinitionOperand << ", ";
+ if (Rule.CommutableSecondUseOperand)
+ Output << *Rule.CommutableSecondUseOperand;
+ else
+ Output << "MacroFusionRule::NoOperand";
+ Output << ", " << (Rule.RequireSingleNonDebugUse ? "true" : "false") << ", "
+ << (Rule.RequireSecondDestinationTie ? "true" : "false") << "},\n";
+ }
+ Output << "}};\n\n";
+ Output << "[[nodiscard]] constexpr std::span<const MacroFusionRule> "
+ "generatedMacroFusionRules() noexcept {\n"
+ " return GeneratedMacroFusionRules;\n"
+ "}\n\n";
+ Output << "#endif // GET_MACRO_FUSION_RULES\n";
+ return Output.str();
+}
+
+} // namespace rcc::targetgen