From 8a4bb6e3b0bffa0ed79b51347b12ee4293b622a7 Mon Sep 17 00:00:00 2001 From: Richard-Qin-X Date: Sat, 22 Aug 2026 18:49:08 +0800 Subject: [CodeGen] Generate RISC-V macro fusion rules --- backend/include/rcc/CodeGen/MIRParser/MIParser.h | 2 +- backend/include/rcc/CodeGen/MachineOperand.h | 7 +- .../rcc/CodeGen/MachineOptimizationPipeline.h | 2 + backend/include/rcc/CodeGen/MachineScheduler.h | 1 + backend/include/rcc/CodeGen/MacroFusion.h | 77 ++++++++++++++++++++++ backend/include/rcc/CodeGen/ScheduleDAG.h | 11 +++- .../include/rcc/CodeGen/TargetSchedulingModel.h | 3 +- 7 files changed, 96 insertions(+), 7 deletions(-) create mode 100644 backend/include/rcc/CodeGen/MacroFusion.h (limited to 'backend/include/rcc/CodeGen') diff --git a/backend/include/rcc/CodeGen/MIRParser/MIParser.h b/backend/include/rcc/CodeGen/MIRParser/MIParser.h index cd40882..4df2ea4 100644 --- a/backend/include/rcc/CodeGen/MIRParser/MIParser.h +++ b/backend/include/rcc/CodeGen/MIRParser/MIParser.h @@ -3,9 +3,9 @@ #ifndef RCC_CODEGEN_MIRPARSER_MIPARSER_H #define RCC_CODEGEN_MIRPARSER_MIPARSER_H +#include "rcc/CodeGen/GlobalObject.h" #include "rcc/CodeGen/MachineIRTypes.h" #include "rcc/CodeGen/MachineMetadata.h" -#include "rcc/CodeGen/GlobalObject.h" #include "rcc/CodeGen/Register.h" #include "rcc/Support/Error.h" #include "rcc/Support/TextDiagnostic.h" diff --git a/backend/include/rcc/CodeGen/MachineOperand.h b/backend/include/rcc/CodeGen/MachineOperand.h index d82e41a..fecb4e0 100644 --- a/backend/include/rcc/CodeGen/MachineOperand.h +++ b/backend/include/rcc/CodeGen/MachineOperand.h @@ -330,9 +330,10 @@ public: std::uint32_t TargetFlags = 0); [[nodiscard]] static MachineOperand jumpTable(JumpTableIndex Index, std::uint32_t TargetFlags = 0); - [[nodiscard]] static Expected - globalSymbol(std::string Name, std::int64_t Offset = 0, std::uint32_t TargetFlags = 0, - GlobalValueProperties Properties = {}); + [[nodiscard]] static Expected globalSymbol(std::string Name, + std::int64_t Offset = 0, + std::uint32_t TargetFlags = 0, + GlobalValueProperties Properties = {}); [[nodiscard]] static Expected externalSymbol(std::string Name, std::int64_t Offset = 0, std::uint32_t TargetFlags = 0); [[nodiscard]] static Expected blockAddress(std::string FunctionName, diff --git a/backend/include/rcc/CodeGen/MachineOptimizationPipeline.h b/backend/include/rcc/CodeGen/MachineOptimizationPipeline.h index 911cb86..d4abf74 100644 --- a/backend/include/rcc/CodeGen/MachineOptimizationPipeline.h +++ b/backend/include/rcc/CodeGen/MachineOptimizationPipeline.h @@ -4,6 +4,7 @@ #define RCC_CODEGEN_MACHINEOPTIMIZATIONPIPELINE_H #include "rcc/CodeGen/MachinePassManager.h" +#include "rcc/CodeGen/MachineScheduler.h" namespace rcc { @@ -21,6 +22,7 @@ struct MachineOptimizationPipelineTargetInfo final { const TargetFrameLowering &FrameLowering; const TargetPseudoExpansionInfo &PseudoExpansion; const TargetSchedulingModel &SchedulingModel; + MachineSchedulerOptions SchedulerOptions; }; struct MachineOptimizationPipelineOptions final { diff --git a/backend/include/rcc/CodeGen/MachineScheduler.h b/backend/include/rcc/CodeGen/MachineScheduler.h index bfe9265..614ef86 100644 --- a/backend/include/rcc/CodeGen/MachineScheduler.h +++ b/backend/include/rcc/CodeGen/MachineScheduler.h @@ -14,6 +14,7 @@ class TargetSchedulingModel; struct MachineSchedulerOptions final { std::size_t MaximumRegionSize = 512; bool EnableBidirectionalScheduling = true; + bool EmitDebugOutput = false; }; class MachineSchedulerPass final : public MachineFunctionPass { diff --git a/backend/include/rcc/CodeGen/MacroFusion.h b/backend/include/rcc/CodeGen/MacroFusion.h new file mode 100644 index 0000000..c3d811d --- /dev/null +++ b/backend/include/rcc/CodeGen/MacroFusion.h @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef RCC_CODEGEN_MACROFUSION_H +#define RCC_CODEGEN_MACROFUSION_H + +#include "rcc/CodeGen/MachineIRTypes.h" +#include "rcc/Support/Error.h" + +#include +#include +#include +#include + +namespace rcc { + +class MachineInstr; +class ScheduleDAG; +class TargetDescription; + +enum class MacroFusionInstruction : std::uint8_t { + First, + Second, +}; + +struct MacroFusionOpcodePair final { + Opcode First; + Opcode Second; +}; + +struct MacroFusionImmediatePredicate final { + MacroFusionInstruction Instruction = MacroFusionInstruction::First; + std::uint32_t OperandIndex = 0; + std::int64_t Minimum = 0; + std::int64_t Maximum = 0; +}; + +struct MacroFusionRegisterInequality final { + MacroFusionInstruction Instruction = MacroFusionInstruction::First; + std::uint32_t LeftOperand = 0; + std::uint32_t RightOperand = 0; +}; + +struct MacroFusionImmediateRelation final { + std::uint32_t FirstOperand = 0; + std::uint32_t SecondOperand = 0; +}; + +struct MacroFusionRule final { + static constexpr std::uint32_t NoOperand = std::numeric_limits::max(); + + std::string_view Name; + std::string_view Feature; + std::span FirstOpcodes; + std::span SecondOpcodes; + std::span OpcodePairs; + std::span ImmediatePredicates; + std::span RegisterInequalities; + std::span ImmediateRelations; + std::uint32_t FirstDefinitionOperand = 0; + std::uint32_t SecondUseOperand = 1; + std::uint32_t SecondDefinitionOperand = 0; + std::uint32_t CommutableSecondUseOperand = NoOperand; + bool RequireSingleNonDebugUse = false; + bool RequireSecondDestinationTie = false; +}; + +[[nodiscard]] bool matchesMacroFusion(const MacroFusionRule &Rule, const MachineInstr *First, + const MachineInstr &Second) noexcept; + +[[nodiscard]] Expected applyMacroFusion(ScheduleDAG &DAG, + std::span Rules, + const TargetDescription &Target, + bool EmitDebugOutput); + +} // namespace rcc + +#endif // RCC_CODEGEN_MACROFUSION_H diff --git a/backend/include/rcc/CodeGen/ScheduleDAG.h b/backend/include/rcc/CodeGen/ScheduleDAG.h index 644d98a..7634202 100644 --- a/backend/include/rcc/CodeGen/ScheduleDAG.h +++ b/backend/include/rcc/CodeGen/ScheduleDAG.h @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -32,6 +33,7 @@ enum class ScheduleDependencyKind : std::uint8_t { Memory, Barrier, Artificial, + Cluster, RegisterUnit, RegisterMask, }; @@ -57,6 +59,8 @@ struct ScheduleUnit final { std::uint64_t Depth = 0; std::uint64_t Height = 0; MachineInstrStableID StableID; + std::optional ClusterPredecessor; + std::optional ClusterSuccessor; }; class ScheduleDAG final { @@ -64,7 +68,7 @@ public: [[nodiscard]] static Expected build(MachineBasicBlock &Block, std::span Instructions, const MachineFunction &Function, const TargetDescription &Target, - const TargetSchedulingModel &Model, ScheduleDAGMode Mode); + const TargetSchedulingModel &Model, ScheduleDAGMode Mode, bool EmitDebugOutput = false); [[nodiscard]] MachineBasicBlock &block() const noexcept { return *Block; @@ -84,6 +88,7 @@ public: [[nodiscard]] Expected addArtificialDependency(std::size_t Source, std::size_t Destination, std::uint32_t Latency); + [[nodiscard]] Expected fuseInstructionPair(std::size_t First, std::size_t Second); private: explicit ScheduleDAG(MachineBasicBlock &Block) : Block(&Block) {} @@ -97,9 +102,11 @@ private: ScheduleDAGMode Mode); [[nodiscard]] Expected buildMemoryDependencies(const TargetDescription &Target); [[nodiscard]] Expected buildOrderDependencies(const TargetDescription &Target); + [[nodiscard]] bool hasPath(std::size_t Source, std::size_t Destination) const; + [[nodiscard]] bool hasDirectDependency(std::size_t Source, std::size_t Destination) const; void addDependency(std::size_t Source, std::size_t Destination, ScheduleDependencyKind Kind, std::uint32_t Latency); - void computeCriticalPaths(); + [[nodiscard]] Expected computeCriticalPaths(); MachineBasicBlock *Block; std::vector Units; diff --git a/backend/include/rcc/CodeGen/TargetSchedulingModel.h b/backend/include/rcc/CodeGen/TargetSchedulingModel.h index 4d7b3ce..5eb7116 100644 --- a/backend/include/rcc/CodeGen/TargetSchedulingModel.h +++ b/backend/include/rcc/CodeGen/TargetSchedulingModel.h @@ -107,7 +107,8 @@ public: [[nodiscard]] virtual Expected mutateScheduleDAG(ScheduleDAG &DAG, const MachineFunction &Function, const TargetDescription &Target, - ScheduleDAGMode Mode) const; + ScheduleDAGMode Mode, + bool EmitDebugOutput) const; [[nodiscard]] virtual std::int64_t candidatePreference(const ScheduleUnit &Unit, ScheduleDirection Direction, const MachineBasicBlock &Block, std::uint64_t BlockFrequency) const noexcept; -- cgit v1.2.3