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/lib/Target/RISCV/CMakeLists.txt | 10 ++ .../RISCV/GISel/RISCVInstructionSelector.cpp | 16 +-- backend/lib/Target/RISCV/RISCV.h | 9 +- backend/lib/Target/RISCV/RISCVInstrInfoI.rccdesc | 10 +- backend/lib/Target/RISCV/RISCVMacroFusion.rccdesc | 139 +++++++++++++++++++++ .../lib/Target/RISCV/RISCVOptimizationPipeline.cpp | 6 +- backend/lib/Target/RISCV/RISCVPipeline.cpp | 27 ++-- backend/lib/Target/RISCV/RISCVScheduling.cpp | 44 +++++-- backend/lib/Target/RISCV/RISCVSubtarget.cpp | 25 +++- 9 files changed, 250 insertions(+), 36 deletions(-) create mode 100644 backend/lib/Target/RISCV/RISCVMacroFusion.rccdesc (limited to 'backend/lib/Target') diff --git a/backend/lib/Target/RISCV/CMakeLists.txt b/backend/lib/Target/RISCV/CMakeLists.txt index 2e1e224..00de7bd 100644 --- a/backend/lib/Target/RISCV/CMakeLists.txt +++ b/backend/lib/Target/RISCV/CMakeLists.txt @@ -20,6 +20,7 @@ set( "${CMAKE_CURRENT_SOURCE_DIR}/RISCVGISelShift.rccdesc" "${CMAKE_CURRENT_SOURCE_DIR}/RISCVGISelFloating.rccdesc" "${CMAKE_CURRENT_SOURCE_DIR}/RISCVGISelCombiner.rccdesc" + "${CMAKE_CURRENT_SOURCE_DIR}/RISCVMacroFusion.rccdesc" ) set(RCCBackendRISCVTableGenArguments) foreach(RCCBackendRISCVDescriptionSource IN LISTS RCCBackendRISCVDescriptionSources) @@ -45,6 +46,10 @@ set( RCCBackendRISCVGeneratedGlobalISelCombiner "${RCC_BACKEND_BINARY_DIR}/generated/lib/Target/RISCV/RISCVGenGlobalISelCombiner.inc" ) +set( + RCCBackendRISCVGeneratedMacroFusion + "${RCC_BACKEND_BINARY_DIR}/generated/lib/Target/RISCV/RISCVGenMacroFusion.inc" +) add_custom_command( OUTPUT @@ -53,6 +58,7 @@ add_custom_command( "${RCCBackendRISCVGeneratedTables}" "${RCCBackendRISCVGeneratedGlobalISel}" "${RCCBackendRISCVGeneratedGlobalISelCombiner}" + "${RCCBackendRISCVGeneratedMacroFusion}" COMMAND "$" ${RCCBackendRISCVTableGenArguments} @@ -61,6 +67,7 @@ add_custom_command( --tables "${RCCBackendRISCVGeneratedTables}" --global-isel "${RCCBackendRISCVGeneratedGlobalISel}" --global-isel-combiner "${RCCBackendRISCVGeneratedGlobalISelCombiner}" + --macro-fusion "${RCCBackendRISCVGeneratedMacroFusion}" DEPENDS RCCBackendTableGenTool ${RCCBackendRISCVDescriptionSources} COMMENT "Generating RCC RV64GC target tables" VERBATIM @@ -74,6 +81,7 @@ add_custom_target( "${RCCBackendRISCVGeneratedTables}" "${RCCBackendRISCVGeneratedGlobalISel}" "${RCCBackendRISCVGeneratedGlobalISelCombiner}" + "${RCCBackendRISCVGeneratedMacroFusion}" ) set_source_files_properties( @@ -82,6 +90,7 @@ set_source_files_properties( "${RCCBackendRISCVGeneratedTables}" "${RCCBackendRISCVGeneratedGlobalISel}" "${RCCBackendRISCVGeneratedGlobalISelCombiner}" + "${RCCBackendRISCVGeneratedMacroFusion}" PROPERTIES GENERATED TRUE HEADER_FILE_ONLY TRUE ) @@ -117,6 +126,7 @@ add_library( "${RCCBackendRISCVGeneratedTables}" "${RCCBackendRISCVGeneratedGlobalISel}" "${RCCBackendRISCVGeneratedGlobalISelCombiner}" + "${RCCBackendRISCVGeneratedMacroFusion}" ) add_library(RCCBackend::RISCV ALIAS RCCBackendRISCV) add_dependencies(RCCBackendRISCV RCCBackendRISCVGeneratedTablesTarget) diff --git a/backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp index 094f9cb..ca702ed 100644 --- a/backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp +++ b/backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp @@ -5,9 +5,9 @@ #include "RISCVInstrInfo.h" #include "RISCVRegisterBankInfo.h" #include "rcc/CodeGen/GenericOpcodes.h" -#include "rcc/CodeGen/GlobalObject.h" #include "rcc/CodeGen/GlobalISel/GISelValueTracking.h" #include "rcc/CodeGen/GlobalISel/InstructionSelector.h" +#include "rcc/CodeGen/GlobalObject.h" #include "rcc/CodeGen/LowLevelType.h" #include "rcc/CodeGen/MachineBasicBlock.h" #include "rcc/CodeGen/MachineFunction.h" @@ -727,8 +727,8 @@ public: } private: - [[nodiscard]] Expected - createGOTLoad(MachineFunction &Function, LowLevelType Type) const { + [[nodiscard]] Expected createGOTLoad(MachineFunction &Function, + LowLevelType Type) const { auto Size = MemorySize::fixed(Type.minimumBitWidth() / 8U); if (!Size) return std::unexpected(Size.error()); @@ -745,9 +745,9 @@ private: return Function.createMemOperand(std::move(Description)); } - [[nodiscard]] Expected - selectGlobalAddress(MachineInstr &Instruction, MachineFunction &Function, - const TargetDescription &Target) const { + [[nodiscard]] Expected selectGlobalAddress(MachineInstr &Instruction, + MachineFunction &Function, + const TargetDescription &Target) const { const MachineOperand *DestinationOperand = Instruction.operandAt(0); const MachineOperand *SymbolOperand = Instruction.operandAt(1); const Register *Destination = @@ -775,8 +775,8 @@ private: } const bool TaggedGlobals = Subtarget.features().has(RISCVSubtargetOption::TaggedGlobals); - const bool UseGOT = Subtarget.relocationModel() == RelocationModel::PositionIndependent || - TaggedGlobals; + const bool UseGOT = + Subtarget.relocationModel() == RelocationModel::PositionIndependent || TaggedGlobals; const auto ReplaceWithPseudo = [&](InstructionOpcode OpcodeValue) -> Expected { auto SetOpcode = Instruction.setOpcode(instructionOpcode(OpcodeValue)); if (!SetOpcode) diff --git a/backend/lib/Target/RISCV/RISCV.h b/backend/lib/Target/RISCV/RISCV.h index 4699091..4eeaf64 100644 --- a/backend/lib/Target/RISCV/RISCV.h +++ b/backend/lib/Target/RISCV/RISCV.h @@ -27,13 +27,18 @@ createRISCVInstructionSelector(const RISCVSubtarget &Subtarget, const RISCVRegisterBankInfo &RegisterBanks); [[nodiscard]] const TargetRegisterAllocationInfo ®isterAllocationInfo() noexcept; [[nodiscard]] const TargetFrameLowering &frameLowering() noexcept; -[[nodiscard]] const TargetSchedulingModel &schedulingModel() noexcept; +[[nodiscard]] std::unique_ptr +createSchedulingHooks(const RISCVSubtargetFeatures &Features); +[[nodiscard]] Expected +createSchedulingModel(const TargetSchedulingHooks &Hooks); [[nodiscard]] const TargetMachineCombinerInfo &machineCombinerInfo() noexcept; [[nodiscard]] const GIMatchTable &giselCombinerTable() noexcept; [[nodiscard]] const GIMatchTableExecutor &giselCombinerExecutor() noexcept; [[nodiscard]] const TargetMemoryFoldingInfo &memoryFoldingInfo() noexcept; [[nodiscard]] const TargetPseudoExpansionInfo &pseudoExpansionInfo() noexcept; -[[nodiscard]] MachineOptimizationPipelineTargetInfo optimizationPipelineInfo() noexcept; +[[nodiscard]] MachineOptimizationPipelineTargetInfo +optimizationPipelineInfo(const RISCVSubtarget &Subtarget, + bool EmitSchedulerDebugOutput = false) noexcept; } // namespace riscv } // namespace rcc diff --git a/backend/lib/Target/RISCV/RISCVInstrInfoI.rccdesc b/backend/lib/Target/RISCV/RISCVInstrInfoI.rccdesc index 7bb30e5..13ea700 100644 --- a/backend/lib/Target/RISCV/RISCVInstrInfoI.rccdesc +++ b/backend/lib/Target/RISCV/RISCVInstrInfoI.rccdesc @@ -188,7 +188,7 @@ instructions: - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS2 } num_explicit_defs: 1 - flags: [produces_code] + flags: [produces_code, commutable] scheduling_class: ALU encoding_category: R assembly_format: RD_RS1_RS2 @@ -233,7 +233,7 @@ instructions: - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS2 } num_explicit_defs: 1 - flags: [produces_code] + flags: [produces_code, commutable] scheduling_class: ALU encoding_category: R assembly_format: RD_RS1_RS2 @@ -248,7 +248,7 @@ instructions: - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS2 } num_explicit_defs: 1 - flags: [produces_code] + flags: [produces_code, commutable] scheduling_class: ALU encoding_category: R assembly_format: RD_RS1_RS2 @@ -263,7 +263,7 @@ instructions: - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS2 } num_explicit_defs: 1 - flags: [produces_code] + flags: [produces_code, commutable] scheduling_class: ALU encoding_category: R assembly_format: RD_RS1_RS2 @@ -666,7 +666,7 @@ instructions: - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS1 } - { kinds: [register], role: use, register_class: GPR, register_bank: GPR, name: RS2 } num_explicit_defs: 1 - flags: [produces_code] + flags: [produces_code, commutable] scheduling_class: ALU encoding_category: R assembly_format: RD_RS1_RS2 diff --git a/backend/lib/Target/RISCV/RISCVMacroFusion.rccdesc b/backend/lib/Target/RISCV/RISCVMacroFusion.rccdesc new file mode 100644 index 0000000..2c432a2 --- /dev/null +++ b/backend/lib/Target/RISCV/RISCVMacroFusion.rccdesc @@ -0,0 +1,139 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +macro_fusion_rules: + - + id: TuneLUIADDIFusion + feature: fusion-lui-addi + first_opcodes: [LUI] + second_opcodes: [ADDI, ADDIW] + link: { first_definition: 0, second_use: 1, second_definition: 0, one_non_debug_use: true, second_destination_tied: true } + - + id: TuneAUIPCADDIFusion + feature: fusion-auipc-addi + first_opcodes: [AUIPC] + second_opcodes: [ADDI] + link: { first_definition: 0, second_use: 1, second_definition: 0, one_non_debug_use: true, second_destination_tied: true } + - + id: TuneZExtHFusion + feature: fusion-zexth + first_opcodes: [SLLI] + second_opcodes: [SRLI] + immediates: + - { instruction: first, operand: 2, min: 48, max: 48 } + - { instruction: second, operand: 2, min: 48, max: 48 } + link: { first_definition: 0, second_use: 1, second_definition: 0, one_non_debug_use: true, second_destination_tied: true } + - + id: TuneZExtWFusion + feature: fusion-zextw + first_opcodes: [SLLI] + second_opcodes: [SRLI] + immediates: + - { instruction: first, operand: 2, min: 32, max: 32 } + - { instruction: second, operand: 2, min: 32, max: 32 } + link: { first_definition: 0, second_use: 1, second_definition: 0, one_non_debug_use: true, second_destination_tied: true } + - + id: TuneShiftedZExtWFusion + feature: fusion-shifted-zextw + first_opcodes: [SLLI] + second_opcodes: [SRLI] + immediates: + - { instruction: first, operand: 2, min: 32, max: 32 } + - { instruction: second, operand: 2, min: 0, max: 31 } + link: { first_definition: 0, second_use: 1, second_definition: 0, one_non_debug_use: true, second_destination_tied: true } + - + id: TuneLDADDFusion + feature: fusion-ld-add + first_opcodes: [ADD] + second_opcodes: [LD] + immediates: + - { instruction: second, operand: 2, min: 0, max: 0 } + link: { first_definition: 0, second_use: 1, second_definition: 0, one_non_debug_use: true, second_destination_tied: true } + - + id: TuneADDLoadFusion + feature: fusion-add-load + first_opcodes: [ADD, ADD_UW] + second_opcodes: [LB, LH, LW, LD, LBU, LHU, LWU] + link: { first_definition: 0, second_use: 1, second_definition: 0, one_non_debug_use: true, second_destination_tied: true } + - + id: TuneAUIPCLoadFusion + feature: fusion-auipc-load + first_opcodes: [AUIPC] + second_opcodes: [LB, LH, LW, LD, LBU, LHU, LWU] + link: { first_definition: 0, second_use: 1, second_definition: 0, one_non_debug_use: true, second_destination_tied: true } + - + id: TuneLUILoadFusion + feature: fusion-lui-load + first_opcodes: [LUI] + second_opcodes: [LB, LH, LW, LD, LBU, LHU, LWU] + link: { first_definition: 0, second_use: 1, second_definition: 0, one_non_debug_use: true, second_destination_tied: true } + - + id: TuneBFExtFusion + feature: fusion-bfext + first_opcodes: [SLLI] + second_opcodes: [SRLI] + link: { first_definition: 0, second_use: 1, second_definition: 0, one_non_debug_use: true, second_destination_tied: true } + - + id: TuneADDILoadFusion + feature: fusion-addi-load + first_opcodes: [ADDI] + second_opcodes: [LB, LH, LW, LD, LBU, LHU, LWU] + link: { first_definition: 0, second_use: 1, second_definition: 0, one_non_debug_use: true, second_destination_tied: true } + - + id: TuneSHXADDLoadFusion + feature: fusion-shxadd-load + first_opcodes: [SH1ADD, SH2ADD, SH3ADD, SH1ADD_UW, SH2ADD_UW, SH3ADD_UW] + second_opcodes: [LB, LH, LW, LD, LBU, LHU, LWU] + link: { first_definition: 0, second_use: 1, second_definition: 0, one_non_debug_use: true, second_destination_tied: true } + - + id: TuneFusionLogicRegReg + feature: fusion-logic-reg-reg + first_opcodes: [AND, OR, XOR] + second_opcodes: [AND, OR, XOR] + link: { first_definition: 0, second_use: 1, second_definition: 0, commutable_second_use: 2, one_non_debug_use: true, second_destination_tied: true } + - + id: TuneFusionLogicRegImm + feature: fusion-logic-reg-imm + first_opcodes: [AND, OR, XOR] + second_opcodes: [ANDI, ORI, XORI] + link: { first_definition: 0, second_use: 1, second_definition: 0, one_non_debug_use: true, second_destination_tied: true } + - + id: TuneFusionLogicImmReg + feature: fusion-logic-imm-reg + first_opcodes: [ANDI, ORI, XORI] + second_opcodes: [AND, OR, XOR] + link: { first_definition: 0, second_use: 1, second_definition: 0, commutable_second_use: 2, one_non_debug_use: true, second_destination_tied: true } + - + id: TuneFusionMulAdd + feature: fusion-mul-add + first_opcodes: [MUL, MULW] + second_opcodes: [ADD, ADDW] + opcode_pairs: + - { first: MUL, second: ADD } + - { first: MULW, second: ADDW } + register_not_equal: + - { instruction: second, left: 0, right: 2 } + link: { first_definition: 0, second_use: 1, second_definition: 0, one_non_debug_use: true, second_destination_tied: true } + - + id: TuneFusionAddMem + feature: fusion-add-mem + first_opcodes: [ADD] + second_opcodes: [LB, LBU, LH, LHU, LW, LWU, LD, FLW, FLD, SB, SH, SW, SD, FSW, FSD] + immediates: + - { instruction: second, operand: 2, min: 0, max: 0 } + register_not_equal: + - { instruction: first, left: 0, right: 1 } + - { instruction: first, left: 0, right: 2 } + link: { first_definition: 0, second_use: 1, second_definition: 0, one_non_debug_use: false, second_destination_tied: false } + - + id: TuneFusionShiftBitExtract + feature: fusion-shift-bit-extract + first_opcodes: [SLLI, SLLIW] + second_opcodes: [SRLI, SRLIW, SRAI, SRAIW] + opcode_pairs: + - { first: SLLI, second: SRLI } + - { first: SLLI, second: SRAI } + - { first: SLLIW, second: SRLIW } + - { first: SLLIW, second: SRAIW } + immediate_relations: + - { kind: less_equal, first_operand: 2, second_operand: 2 } + link: { first_definition: 0, second_use: 1, second_definition: 0, one_non_debug_use: true, second_destination_tied: true } diff --git a/backend/lib/Target/RISCV/RISCVOptimizationPipeline.cpp b/backend/lib/Target/RISCV/RISCVOptimizationPipeline.cpp index 5bacc9c..7571832 100644 --- a/backend/lib/Target/RISCV/RISCVOptimizationPipeline.cpp +++ b/backend/lib/Target/RISCV/RISCVOptimizationPipeline.cpp @@ -5,14 +5,16 @@ namespace rcc::riscv { -MachineOptimizationPipelineTargetInfo optimizationPipelineInfo() noexcept { +MachineOptimizationPipelineTargetInfo +optimizationPipelineInfo(const RISCVSubtarget &Subtarget, bool EmitSchedulerDebugOutput) noexcept { return { .InstrInfo = instrInfo(), .Combiner = machineCombinerInfo(), .MemoryFolding = memoryFoldingInfo(), .FrameLowering = frameLowering(), .PseudoExpansion = pseudoExpansionInfo(), - .SchedulingModel = schedulingModel(), + .SchedulingModel = Subtarget.schedulingModel(), + .SchedulerOptions = {.EmitDebugOutput = EmitSchedulerDebugOutput}, }; } diff --git a/backend/lib/Target/RISCV/RISCVPipeline.cpp b/backend/lib/Target/RISCV/RISCVPipeline.cpp index c24c57f..2af1d43 100644 --- a/backend/lib/Target/RISCV/RISCVPipeline.cpp +++ b/backend/lib/Target/RISCV/RISCVPipeline.cpp @@ -55,8 +55,11 @@ template return addPass(Pipeline, Subtarget.getInstructionSelector()); } -[[nodiscard]] Expected addSSAExitPipeline(MachineFunctionPassManager &Pipeline) { - auto Added = addSelectedSSAOptimizationPipeline(Pipeline, optimizationPipelineInfo()); +[[nodiscard]] Expected addSSAExitPipeline(MachineFunctionPassManager &Pipeline, + const RISCVSubtarget &Subtarget, + RISCVPipelineOptions Options) { + auto Added = addSelectedSSAOptimizationPipeline( + Pipeline, optimizationPipelineInfo(Subtarget, Options.DebugMachineScheduler)); if (!Added) return std::unexpected(Added.error()); Added = addPass(Pipeline, instrInfo()); @@ -65,11 +68,14 @@ template return addPass(Pipeline, instrInfo()); } -[[nodiscard]] Expected addRegisterAllocationPipeline(MachineFunctionPassManager &Pipeline) { +[[nodiscard]] Expected addRegisterAllocationPipeline(MachineFunctionPassManager &Pipeline, + const RISCVSubtarget &Subtarget, + RISCVPipelineOptions Options) { auto Added = addPass(Pipeline, pseudoExpansionInfo()); if (!Added) return std::unexpected(Added.error()); - Added = addPreRegisterAllocationOptimizationPipeline(Pipeline, optimizationPipelineInfo()); + Added = addPreRegisterAllocationOptimizationPipeline( + Pipeline, optimizationPipelineInfo(Subtarget, Options.DebugMachineScheduler)); if (!Added) return std::unexpected(Added.error()); return addPass(Pipeline, registerAllocationInfo()); @@ -81,14 +87,14 @@ template auto Added = addInitialPipeline(Pipeline, Subtarget, Options); if (!Added) return std::unexpected(Added.error()); - Added = addSSAExitPipeline(Pipeline); + Added = addSSAExitPipeline(Pipeline, Subtarget, Options); if (!Added) return std::unexpected(Added.error()); - Added = addRegisterAllocationPipeline(Pipeline); + Added = addRegisterAllocationPipeline(Pipeline, Subtarget, Options); if (!Added) return std::unexpected(Added.error()); return addPostRegisterAllocationPipeline( - Pipeline, optimizationPipelineInfo(), + Pipeline, optimizationPipelineInfo(Subtarget, Options.DebugMachineScheduler), MachineOptimizationPipelineOptions{.UseTargetCopyInstructions = Options.UseTargetCopyInstructions}); } @@ -119,7 +125,8 @@ Expected addCanonicalPipeline(MachineFunctionPassManager &Pipeline, return std::unexpected(Added.error()); } if (!Function.properties().has(MachineFunctionProperty::TiedOpsRewritten)) { - auto Added = addSelectedSSAOptimizationPipeline(Pipeline, optimizationPipelineInfo()); + auto Added = addSelectedSSAOptimizationPipeline( + Pipeline, optimizationPipelineInfo(Subtarget, Options.DebugMachineScheduler)); if (!Added) return std::unexpected(Added.error()); if (!Function.properties().has(MachineFunctionProperty::NoPHIs)) { @@ -134,13 +141,13 @@ Expected addCanonicalPipeline(MachineFunctionPassManager &Pipeline, return std::unexpected(Added.error()); } if (!Function.properties().has(MachineFunctionProperty::NoVRegs)) { - auto Added = addRegisterAllocationPipeline(Pipeline); + auto Added = addRegisterAllocationPipeline(Pipeline, Subtarget, Options); if (!Added) return std::unexpected(Added.error()); } if (!Function.properties().has(MachineFunctionProperty::NoExecutablePseudos)) { auto Added = addPostRegisterAllocationPipeline( - Pipeline, optimizationPipelineInfo(), + Pipeline, optimizationPipelineInfo(Subtarget, Options.DebugMachineScheduler), MachineOptimizationPipelineOptions{.UseTargetCopyInstructions = Options.UseTargetCopyInstructions}); if (!Added) diff --git a/backend/lib/Target/RISCV/RISCVScheduling.cpp b/backend/lib/Target/RISCV/RISCVScheduling.cpp index a58b913..b7947d4 100644 --- a/backend/lib/Target/RISCV/RISCVScheduling.cpp +++ b/backend/lib/Target/RISCV/RISCVScheduling.cpp @@ -1,11 +1,15 @@ // SPDX-License-Identifier: GPL-3.0-or-later #include "RISCV.h" +#include "rcc/CodeGen/MacroFusion.h" +#include "rcc/CodeGen/ScheduleDAG.h" #include "rcc/Target/RISCV/RISCVTarget.h" +#include #include -#include +#include #include +#include #include #include #include @@ -13,6 +17,28 @@ namespace rcc::riscv { namespace { +#define GET_MACRO_FUSION_RULES +#include "RISCVGenMacroFusion.inc" + +class RISCVSchedulingHooks final : public TargetSchedulingHooks { +public: + explicit RISCVSchedulingHooks(const RISCVSubtargetFeatures &Features) { + for (const MacroFusionRule &Rule : generatedMacroFusionRules()) { + if (Features.hasFeature(Rule.Feature)) + MacroFusionRules.push_back(Rule); + } + } + + [[nodiscard]] Expected mutateScheduleDAG(ScheduleDAG &DAG, const MachineFunction &, + const TargetDescription &Target, ScheduleDAGMode, + bool EmitDebugOutput) const override { + return applyMacroFusion(DAG, MacroFusionRules, Target, EmitDebugOutput); + } + +private: + std::vector MacroFusionRules; +}; + enum class Resource : std::uint32_t { Core = 1, IntegerALU = 2, @@ -72,7 +98,7 @@ enum class PressureSet : std::uint32_t { return {}; } -[[nodiscard]] TargetSchedulingModelDesc createDescription() { +[[nodiscard]] TargetSchedulingModelDesc createDescription(const TargetSchedulingHooks &Hooks) { TargetSchedulingModelDesc Description; Description.IssueWidth = 2; Description.DispatchLimit = 2; @@ -121,17 +147,19 @@ enum class PressureSet : std::uint32_t { registerClass(RegisterClass::FPR32), registerClass(RegisterClass::FPR32C)}, 32}, }; + Description.Hooks = &Hooks; return Description; } } // namespace -const TargetSchedulingModel &schedulingModel() noexcept { - static const Expected Model = - TargetSchedulingModel::create(createDescription()); - if (!Model) - std::abort(); - return *Model; +std::unique_ptr +createSchedulingHooks(const RISCVSubtargetFeatures &Features) { + return std::make_unique(Features); +} + +Expected createSchedulingModel(const TargetSchedulingHooks &Hooks) { + return TargetSchedulingModel::create(createDescription(Hooks)); } } // namespace rcc::riscv diff --git a/backend/lib/Target/RISCV/RISCVSubtarget.cpp b/backend/lib/Target/RISCV/RISCVSubtarget.cpp index 4b3064d..c30c898 100644 --- a/backend/lib/Target/RISCV/RISCVSubtarget.cpp +++ b/backend/lib/Target/RISCV/RISCVSubtarget.cpp @@ -7,10 +7,13 @@ #include "GISel/RISCVRegisterBankInfo.h" #include "RISCV.h" #include "rcc/CodeGen/GlobalISel/InstructionSelector.h" +#include "rcc/CodeGen/TargetSchedulingModel.h" #include #include +#include #include +#include namespace rcc::riscv { namespace { @@ -50,6 +53,7 @@ constexpr std::array OptionNames{ OptionName{"fusion-addi-load", RISCVSubtargetOption::FusionAddImmediateLoad}, OptionName{"fusion-auipc-addi", RISCVSubtargetOption::FusionAUIPCAddImmediate}, OptionName{"fusion-auipc-load", RISCVSubtargetOption::FusionAUIPCLoad}, + OptionName{"fusion-bfext", RISCVSubtargetOption::FusionBitfieldExtract}, OptionName{"fusion-ld-add", RISCVSubtargetOption::FusionLoadDoubleAdd}, OptionName{"fusion-logic-imm-reg", RISCVSubtargetOption::FusionLogicImmediateRegister}, OptionName{"fusion-logic-reg-imm", RISCVSubtargetOption::FusionLogicRegisterImmediate}, @@ -58,6 +62,7 @@ constexpr std::array OptionNames{ OptionName{"fusion-lui-load", RISCVSubtargetOption::FusionLUILoad}, OptionName{"fusion-mul-add", RISCVSubtargetOption::FusionMultiplyAdd}, OptionName{"fusion-shift-bit-extract", RISCVSubtargetOption::FusionShiftBitExtract}, + OptionName{"fusion-shxadd-load", RISCVSubtargetOption::FusionShiftedAddLoad}, OptionName{"fusion-shifted-zextw", RISCVSubtargetOption::FusionShiftedZeroExtendWord}, OptionName{"fusion-zexth", RISCVSubtargetOption::FusionZeroExtendHalf}, OptionName{"fusion-zextw", RISCVSubtargetOption::FusionZeroExtendWord}, @@ -171,9 +176,23 @@ bool RISCVSubtargetFeatures::has(RISCVSubtargetOption Option) const noexcept { return (Options & optionBit(Option)) != 0; } +bool RISCVSubtargetFeatures::hasFeature(std::string_view Feature) const noexcept { + if (const OptionName *Option = findOption(Feature)) + return has(Option->Option); + if (const ExtensionName *Extension = findExtension(Feature)) + return has(Extension->Extension); + return false; +} + RISCVSubtarget::RISCVSubtarget(RISCVSubtargetFeatures Features, RelocationModel Relocation, CodeModel Code) - : Features(Features), Relocation(Relocation), Code(Code) {} + : Features(Features), Relocation(Relocation), Code(Code), + SchedulingHooks(createSchedulingHooks(Features)) { + auto Model = createSchedulingModel(*SchedulingHooks); + if (!Model) + std::abort(); + SchedulingModel = std::make_unique(std::move(*Model)); +} RISCVSubtarget::~RISCVSubtarget() = default; @@ -201,4 +220,8 @@ const RISCVRegisterBankInfo *RISCVSubtarget::getRegBankInfo() const { return RegBankInfo.get(); } +const TargetSchedulingModel &RISCVSubtarget::schedulingModel() const noexcept { + return *SchedulingModel; +} + } // namespace rcc::riscv -- cgit v1.2.3