From 0bb35fa2306a66f1f0baf118619b5c1640ed9c01 Mon Sep 17 00:00:00 2001 From: Richard-Qin-X Date: Wed, 12 Aug 2026 21:56:37 +0800 Subject: [GlobalISel] Split the generic pipeline components --- backend/lib/CodeGen/CMakeLists.txt | 8 +- backend/lib/CodeGen/GlobalISel/CMakeLists.txt | 32 + .../lib/CodeGen/GlobalISel/InstructionSelect.cpp | 351 ++++++++++ backend/lib/CodeGen/GlobalISel/Legalizer.cpp | 324 +++++++++ backend/lib/CodeGen/GlobalISel/RegBankSelect.cpp | 238 +++++++ backend/lib/CodeGen/MachinePipelinePasses.cpp | 742 --------------------- backend/lib/Target/RISCV/RISCVCodeGen.cpp | 14 +- backend/lib/Target/RISCV/RISCVPipeline.cpp | 16 +- 8 files changed, 964 insertions(+), 761 deletions(-) create mode 100644 backend/lib/CodeGen/GlobalISel/CMakeLists.txt create mode 100644 backend/lib/CodeGen/GlobalISel/InstructionSelect.cpp create mode 100644 backend/lib/CodeGen/GlobalISel/Legalizer.cpp create mode 100644 backend/lib/CodeGen/GlobalISel/RegBankSelect.cpp delete mode 100644 backend/lib/CodeGen/MachinePipelinePasses.cpp (limited to 'backend/lib') diff --git a/backend/lib/CodeGen/CMakeLists.txt b/backend/lib/CodeGen/CMakeLists.txt index 3a1f34c..996f771 100644 --- a/backend/lib/CodeGen/CMakeLists.txt +++ b/backend/lib/CodeGen/CMakeLists.txt @@ -45,7 +45,6 @@ set( MachineOptimizationPipeline.cpp MachinePass.cpp MachinePseudoExpansion.cpp - MachinePipelinePasses.cpp MachineRegisterInfo.cpp MachineScheduler.cpp MachineShrinkWrapping.cpp @@ -129,13 +128,11 @@ set( "${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/MachineOptimizationPipeline.h" "${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/MachinePass.h" "${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/MachinePseudoExpansion.h" - "${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/MachinePipelinePasses.h" "${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/PrologueEpilogueInsertion.h" "${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/RegisterPressure.h" "${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/RegisterScavenger.h" "${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/ScheduleDAG.h" "${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/ScheduleHazardRecognizer.h" - "${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/TargetCodeGen.h" "${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/TargetFrameLowering.h" "${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/MachineRegisterInfo.h" "${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/MachineScheduler.h" @@ -163,6 +160,7 @@ set( "${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/MachineFunctionProperties.h" "${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/MachineFunctionRecords.h" "${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/Register.h" + "${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/RegisterBankInfo.h" "${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/RegisterMask.h" "${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/StableID.h" "${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/TargetConstant.h" @@ -180,6 +178,8 @@ set( add_library(RCCBackendCodeGen ${RCCBackendCodeGenSources}) add_library(RCCBackend::CodeGen ALIAS RCCBackendCodeGen) +add_subdirectory(GlobalISel) + rcc_backend_configure_target(RCCBackendCodeGen) target_include_directories( @@ -248,7 +248,6 @@ rcc_backend_register_format_files( "${CMAKE_CURRENT_SOURCE_DIR}/MachineOptimizationPipeline.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/MachinePass.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/MachinePseudoExpansion.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/MachinePipelinePasses.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/MachineRegisterInfo.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/MachineScheduler.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/MachineSchedulerInternal.h" @@ -331,7 +330,6 @@ rcc_backend_register_tidy_files( "${CMAKE_CURRENT_SOURCE_DIR}/MachineOptimizationPipeline.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/MachinePass.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/MachinePseudoExpansion.cpp" - "${CMAKE_CURRENT_SOURCE_DIR}/MachinePipelinePasses.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/MachineRegisterInfo.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/MachineScheduler.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/MachineShrinkWrapping.cpp" diff --git a/backend/lib/CodeGen/GlobalISel/CMakeLists.txt b/backend/lib/CodeGen/GlobalISel/CMakeLists.txt new file mode 100644 index 0000000..8a37497 --- /dev/null +++ b/backend/lib/CodeGen/GlobalISel/CMakeLists.txt @@ -0,0 +1,32 @@ +# SPDX-License-Identifier: GPL-3.0-or-later + +set( + RCCBackendGlobalISelSources + InstructionSelect.cpp + Legalizer.cpp + RegBankSelect.cpp +) + +set( + RCCBackendGlobalISelHeaders + "${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/GlobalISel/InstructionSelect.h" + "${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/GlobalISel/InstructionSelector.h" + "${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/GlobalISel/Legalizer.h" + "${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/GlobalISel/LegalizerInfo.h" + "${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/GlobalISel/RegBankSelect.h" +) + +target_sources(RCCBackendCodeGen PRIVATE ${RCCBackendGlobalISelSources}) + +rcc_backend_register_format_files( + "${CMAKE_CURRENT_SOURCE_DIR}/InstructionSelect.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/Legalizer.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/RegBankSelect.cpp" + ${RCCBackendGlobalISelHeaders} +) + +rcc_backend_register_tidy_files( + "${CMAKE_CURRENT_SOURCE_DIR}/InstructionSelect.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/Legalizer.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/RegBankSelect.cpp" +) diff --git a/backend/lib/CodeGen/GlobalISel/InstructionSelect.cpp b/backend/lib/CodeGen/GlobalISel/InstructionSelect.cpp new file mode 100644 index 0000000..8937fd8 --- /dev/null +++ b/backend/lib/CodeGen/GlobalISel/InstructionSelect.cpp @@ -0,0 +1,351 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "rcc/CodeGen/GlobalISel/InstructionSelect.h" + +#include "rcc/CodeGen/MachineBasicBlock.h" +#include "rcc/CodeGen/MachineFunction.h" +#include "rcc/CodeGen/MachineFunctionCloner.h" +#include "rcc/CodeGen/MachineInstr.h" +#include "rcc/CodeGen/MachineLiveness.h" +#include "rcc/CodeGen/MachineRegisterInfo.h" +#include "rcc/CodeGen/TargetDescription.h" + +#include +#include +#include +#include +#include +#include +#include + +namespace rcc { +namespace { + +[[nodiscard]] const MachinePassContract &instructionSelectContract() { + static const MachinePassContract Contract{ + .Name = "instruction-select", + .Requires = {MachineFunctionProperty::Legalized, MachineFunctionProperty::RegBankSelected}, + .Sets = {MachineFunctionProperty::Selected}, + .Clears = {}, + .RequiredAnalyses = {}, + .VerificationStage = PipelineStage::Selected, + }; + return Contract; +} + +struct OpcodeState final { + MachineInstrStableID Instruction; + Opcode OpcodeValue; + std::uint64_t OperandFingerprint = 0; + + friend bool operator==(const OpcodeState &Left, const OpcodeState &Right) noexcept = default; +}; + +struct OpcodeStateHash final { + [[nodiscard]] std::size_t operator()(const OpcodeState &State) const noexcept { + return std::hash{}(State.Instruction.value()) ^ + (std::hash{}(State.OpcodeValue.value()) << 1U) ^ + (std::hash{}(State.OperandFingerprint) << 2U); + } +}; + +void combineFingerprint(std::uint64_t &State, std::uint64_t Value) noexcept { + State ^= Value + 0x9e3779b97f4a7c15ULL + (State << 6U) + (State >> 2U); +} + +[[nodiscard]] std::uint64_t operandFingerprint(const MachineInstr &Instruction) noexcept { + std::uint64_t Result = 0xcbf29ce484222325ULL; + combineFingerprint(Result, Instruction.flags().rawValue()); + combineFingerprint(Result, Instruction.operandCount()); + for (const MachineOperand &Operand : Instruction.operands()) { + combineFingerprint(Result, static_cast(Operand.kind())); + combineFingerprint(Result, Operand.targetFlags()); + combineFingerprint(Result, Operand.registerFlags().rawValue()); + combineFingerprint(Result, Operand.subReg().value()); + if (const Register *Reg = Operand.getIf()) + combineFingerprint(Result, Reg->opaqueValue()); + else if (const std::int64_t *Immediate = Operand.getIf()) + combineFingerprint(Result, static_cast(*Immediate)); + else if (const auto *Integer = Operand.getIf()) + combineFingerprint(Result, Integer->Value.bitWidth()); + else if (const auto *Floating = Operand.getIf()) + combineFingerprint(Result, static_cast(Floating->Bits.semantics())); + else if (const auto *Block = Operand.getIf()) + combineFingerprint(Result, Block->Block == nullptr ? 0 : Block->Block->stableID().value()); + } + return Result; +} + +[[nodiscard]] OpcodeState stateOf(const MachineInstr &Instruction) noexcept { + return {Instruction.stableID(), Instruction.opcode(), operandFingerprint(Instruction)}; +} + +[[nodiscard]] std::vector layoutInstructions(MachineFunction &Function) { + std::vector Result; + for (MachineBasicBlock *Block = Function.firstBlock(); Block != nullptr; Block = Block->next()) + for (MachineInstr *Instruction = Block->firstInstruction(); Instruction != nullptr; + Instruction = Instruction->next()) + Result.push_back(Instruction); + return Result; +} + +[[nodiscard]] std::vector stableCFGPostOrder(MachineFunction &Function) { + std::vector Roots; + for (MachineBasicBlock *Block = Function.firstBlock(); Block != nullptr; Block = Block->next()) + Roots.push_back(Block); + std::ranges::sort(Roots, {}, + [](const MachineBasicBlock *Block) { return Block->stableID().value(); }); + if (MachineBasicBlock *Entry = Function.firstBlock(); Entry != nullptr) { + const auto Position = std::ranges::find(Roots, Entry); + if (Position != Roots.end()) + std::rotate(Roots.begin(), Position, std::next(Position)); + } + + struct TraversalFrame final { + MachineBasicBlock *Block = nullptr; + std::vector Successors; + std::size_t NextSuccessor = 0; + }; + const auto MakeFrame = [](MachineBasicBlock &Block) { + TraversalFrame Frame; + Frame.Block = &Block; + for (const MachineSuccessor &Successor : Block.successors()) { + if (Successor.Block != nullptr) + Frame.Successors.push_back(Successor.Block); + } + std::ranges::sort(Frame.Successors, {}, [](const MachineBasicBlock *Successor) { + return Successor->stableID().value(); + }); + return Frame; + }; + + std::vector Result; + std::unordered_set Visited; + std::vector Stack; + for (MachineBasicBlock *Root : Roots) { + if (!Visited.insert(Root).second) + continue; + Stack.push_back(MakeFrame(*Root)); + while (!Stack.empty()) { + TraversalFrame &Frame = Stack.back(); + if (Frame.NextSuccessor < Frame.Successors.size()) { + MachineBasicBlock *Successor = Frame.Successors[Frame.NextSuccessor++]; + if (Visited.insert(Successor).second) + Stack.push_back(MakeFrame(*Successor)); + continue; + } + Result.push_back(Frame.Block); + Stack.pop_back(); + } + } + return Result; +} + +[[nodiscard]] std::vector bottomUpInstructions(MachineFunction &Function) { + std::vector Result; + for (MachineBasicBlock *Block : stableCFGPostOrder(Function)) { + for (MachineInstr *Instruction = Block->lastInstruction(); Instruction != nullptr; + Instruction = Instruction->previous()) + Result.push_back(Instruction); + } + return Result; +} + +[[nodiscard]] Expected requireProperties(const MachineFunction &Function, + const MachinePassContract &Contract) { + const MachineFunctionProperties Missing = Contract.Requires.missingFrom(Function.properties()); + if (!Missing.empty()) { + return makeUnexpected(ErrorCode::VerificationError, + "pass '" + Contract.Name + + "' requires properties: " + Missing.toString()); + } + return {}; +} + +[[nodiscard]] Error passFailure(std::string Message, + ErrorCode Code = ErrorCode::VerificationError) { + return Error(Code, std::move(Message)); +} + +[[nodiscard]] Error prefixedError(const Error &Source, std::string Prefix) { + Prefix.append(Source.message()); + return Error(Source.code(), std::move(Prefix)); +} + +[[nodiscard]] Expected repairTrackedLiveness(MachineFunction &Function, + const TargetDescription &Target, + MachinePassResult &Result) { + if (!Result.Changed || !Function.properties().has(MachineFunctionProperty::TracksLiveness)) { + return {}; + } + auto Rebuilt = rebuildMachineLiveness(Function, Target); + if (!Rebuilt) + return std::unexpected(Rebuilt.error()); + if (*Rebuilt) + Result.Changes.add(MachinePassChange::Operands); + return {}; +} + +} // namespace + +const MachinePassContract &InstructionSelect::contract() const noexcept { + return instructionSelectContract(); +} + +Expected InstructionSelect::run(MachineFunction &Function, + const TargetDescription &Target, + MachineAnalysisManager &Analyses) { + if (Info == nullptr) + return std::unexpected(passFailure("instruction select has no target behavior interface", + ErrorCode::InvalidArgument)); + auto Required = requireProperties(Function, contract()); + if (!Required) + return std::unexpected(Required.error()); + + auto Trial = cloneMachineFunction( + Function, Target, + MachineFunctionCloneOptions{.NewStableID = Function.stableID(), .NewName = std::nullopt}); + if (!Trial) { + return std::unexpected( + prefixedError(Trial.error(), "instruction-selection transaction setup failed: ")); + } + MachineActionReplay Actions(Analyses, Trial->InstructionStableIDs); + auto TrialResult = runImplementation(*Trial->ClonedFunction, Target, Actions); + if (!TrialResult) + return std::unexpected(TrialResult.error()); + Actions.beginReplay(); + auto Result = runImplementation(Function, Target, Actions); + if (!Result) { + return std::unexpected( + prefixedError(Result.error(), + "instruction selection diverged after a successful transaction preflight: ")); + } + auto Replayed = Actions.finishReplay(); + if (!Replayed) + return std::unexpected(Replayed.error()); + return Result; +} + +Expected InstructionSelect::runImplementation(MachineFunction &Function, + const TargetDescription &Target, + MachineActionReplay &Actions) { + + MachinePassResult Result; + std::vector Worklist; + std::unordered_set DiscoveredInstructions; + std::unordered_set SeenStates; + for (MachineInstr *Instruction : bottomUpInstructions(Function)) { + const InstructionDescriptor *Descriptor = Target.instructionDescriptor(Instruction->opcode()); + if (Descriptor == nullptr) + return std::unexpected( + passFailure("instruction selector encountered an unknown instruction descriptor")); + auto Validation = Target.validateInstruction(*Instruction, Function.registerInfo()); + if (!Validation) + return std::unexpected( + prefixedError(Validation.error(), "instruction selector input is invalid: ")); + if (!Descriptor->Flags.has(InstructionFlag::Generic)) + continue; + auto Match = Info->canSelect(*Instruction, Function, Target); + if (!Match) + return std::unexpected(Match.error()); + Worklist.push_back(Instruction); + DiscoveredInstructions.insert(Instruction->stableID()); + } + + for (std::size_t Index = 0; Index < Worklist.size(); ++Index) { + MachineInstr *Instruction = Worklist[Index]; + if (Instruction->parent() == nullptr) + return std::unexpected(passFailure("instruction selector lost its input instruction")); + const InstructionDescriptor *CurrentDescriptor = + Target.instructionDescriptor(Instruction->opcode()); + if (CurrentDescriptor == nullptr) + return std::unexpected( + passFailure("instruction selector encountered an unknown instruction descriptor")); + if (!CurrentDescriptor->Flags.has(InstructionFlag::Generic)) + continue; + const OpcodeState Before = stateOf(*Instruction); + if (!SeenStates.insert(Before).second) { + return std::unexpected(passFailure("instruction selector entered a repeated state for '" + + CurrentDescriptor->Name + "'", + ErrorCode::InternalError)); + } + auto Match = Info->canSelect(*Instruction, Function, Target); + if (!Match) + return std::unexpected(Match.error()); + std::string Rule = "select."; + Rule.append(CurrentDescriptor->Name); + auto Accepted = Actions.request(Rule, Function, Instruction->stableID()); + if (!Accepted) + return std::unexpected(Accepted.error()); + if (!*Accepted) { + return std::unexpected(passFailure("required selection action was rejected for '" + + CurrentDescriptor->Name + "'", + ErrorCode::VerificationError)); + } + auto Selection = Info->select(*Instruction, Function, Target); + if (!Selection) + return std::unexpected(Selection.error()); + const InstructionDescriptor *Selected = Target.instructionDescriptor(Instruction->opcode()); + if (Selected == nullptr) + return std::unexpected( + passFailure("instruction selector produced an unknown instruction descriptor")); + auto Constraint = Info->constrainSelectedInstruction(*Instruction, Function, Target); + if (!Constraint) { + return std::unexpected(prefixedError( + Constraint.error(), "instruction selector could not constrain selected registers: ")); + } + auto Validation = Target.validateInstruction(*Instruction, Function.registerInfo()); + if (!Validation) + return std::unexpected( + prefixedError(Validation.error(), "instruction selector produced invalid MachineIR: ")); + const OpcodeState After = stateOf(*Instruction); + if (After == Before) + return std::unexpected( + passFailure("instruction selector reported success without observable progress", + ErrorCode::InternalError)); + Result.Changed = true; + Result.Changes.add(MachinePassChange::Instructions); + if (Selected->Flags.has(InstructionFlag::Generic)) + Worklist.push_back(Instruction); + for (MachineInstr *Candidate : bottomUpInstructions(Function)) { + const InstructionDescriptor *CandidateDescriptor = + Target.instructionDescriptor(Candidate->opcode()); + if (CandidateDescriptor == nullptr) + return std::unexpected( + passFailure("instruction selector produced an unknown instruction descriptor")); + if (!CandidateDescriptor->Flags.has(InstructionFlag::Generic) || + !DiscoveredInstructions.insert(Candidate->stableID()).second) { + continue; + } + auto CandidateMatch = Info->canSelect(*Candidate, Function, Target); + if (!CandidateMatch) + return std::unexpected(CandidateMatch.error()); + Worklist.push_back(Candidate); + } + } + for (MachineInstr *Instruction : layoutInstructions(Function)) { + const InstructionDescriptor *Descriptor = Target.instructionDescriptor(Instruction->opcode()); + if (Descriptor == nullptr) + return std::unexpected( + passFailure("instruction selector produced an unknown instruction descriptor")); + auto Validation = Target.validateInstruction(*Instruction, Function.registerInfo()); + if (!Validation) + return std::unexpected( + prefixedError(Validation.error(), "instruction selector produced invalid MachineIR: ")); + if (Descriptor->Flags.has(InstructionFlag::Generic)) + return std::unexpected( + passFailure("instruction selector left a generic opcode in the function")); + } + auto RegisterValidation = Target.validateRegisterInfo(Function.registerInfo()); + if (!RegisterValidation) + return std::unexpected(prefixedError(RegisterValidation.error(), + "instruction selection produced invalid registers: ")); + auto Liveness = repairTrackedLiveness(Function, Target, Result); + if (!Liveness) { + return std::unexpected( + prefixedError(Liveness.error(), "instruction-selection liveness repair failed: ")); + } + Result.Preserved = Result.Changed ? PreservedAnalyses::none() : PreservedAnalyses::all(); + return Result; +} +} // namespace rcc diff --git a/backend/lib/CodeGen/GlobalISel/Legalizer.cpp b/backend/lib/CodeGen/GlobalISel/Legalizer.cpp new file mode 100644 index 0000000..e61a801 --- /dev/null +++ b/backend/lib/CodeGen/GlobalISel/Legalizer.cpp @@ -0,0 +1,324 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "rcc/CodeGen/GlobalISel/Legalizer.h" + +#include "rcc/CodeGen/MachineBasicBlock.h" +#include "rcc/CodeGen/MachineFunction.h" +#include "rcc/CodeGen/MachineFunctionCloner.h" +#include "rcc/CodeGen/MachineInstr.h" +#include "rcc/CodeGen/MachineLiveness.h" +#include "rcc/CodeGen/MachineRegisterInfo.h" +#include "rcc/CodeGen/TargetDescription.h" + +#include +#include +#include +#include +#include +#include + +namespace rcc { +namespace { + +[[nodiscard]] const MachinePassContract &legalizerContract() { + static const MachinePassContract Contract{ + .Name = "legalizer", + // LLVM's GlobalISel legalizer operates on SSA form and does not require + // the optional register-liveness tracking property. + .Requires = {MachineFunctionProperty::IsSSA}, + .Sets = {MachineFunctionProperty::Legalized}, + .Clears = {}, + .RequiredAnalyses = {}, + .VerificationStage = PipelineStage::Legalized, + }; + return Contract; +} + +struct OpcodeState final { + MachineInstrStableID Instruction; + Opcode OpcodeValue; + std::uint64_t OperandFingerprint = 0; + + friend bool operator==(const OpcodeState &Left, const OpcodeState &Right) noexcept = default; +}; + +struct OpcodeStateHash final { + [[nodiscard]] std::size_t operator()(const OpcodeState &State) const noexcept { + return std::hash{}(State.Instruction.value()) ^ + (std::hash{}(State.OpcodeValue.value()) << 1U) ^ + (std::hash{}(State.OperandFingerprint) << 2U); + } +}; + +void combineFingerprint(std::uint64_t &State, std::uint64_t Value) noexcept { + State ^= Value + 0x9e3779b97f4a7c15ULL + (State << 6U) + (State >> 2U); +} + +[[nodiscard]] std::uint64_t operandFingerprint(const MachineInstr &Instruction) noexcept { + std::uint64_t Result = 0xcbf29ce484222325ULL; + combineFingerprint(Result, Instruction.flags().rawValue()); + combineFingerprint(Result, Instruction.operandCount()); + for (const MachineOperand &Operand : Instruction.operands()) { + combineFingerprint(Result, static_cast(Operand.kind())); + combineFingerprint(Result, Operand.targetFlags()); + combineFingerprint(Result, Operand.registerFlags().rawValue()); + combineFingerprint(Result, Operand.subReg().value()); + if (const Register *Reg = Operand.getIf()) + combineFingerprint(Result, Reg->opaqueValue()); + else if (const std::int64_t *Immediate = Operand.getIf()) + combineFingerprint(Result, static_cast(*Immediate)); + else if (const auto *Integer = Operand.getIf()) + combineFingerprint(Result, Integer->Value.bitWidth()); + else if (const auto *Floating = Operand.getIf()) + combineFingerprint(Result, static_cast(Floating->Bits.semantics())); + else if (const auto *Block = Operand.getIf()) + combineFingerprint(Result, Block->Block == nullptr ? 0 : Block->Block->stableID().value()); + } + return Result; +} + +[[nodiscard]] OpcodeState stateOf(const MachineInstr &Instruction) noexcept { + return {Instruction.stableID(), Instruction.opcode(), operandFingerprint(Instruction)}; +} + +[[nodiscard]] std::vector layoutInstructions(MachineFunction &Function) { + std::vector Result; + for (MachineBasicBlock *Block = Function.firstBlock(); Block != nullptr; Block = Block->next()) + for (MachineInstr *Instruction = Block->firstInstruction(); Instruction != nullptr; + Instruction = Instruction->next()) + Result.push_back(Instruction); + return Result; +} + +[[nodiscard]] Expected requireProperties(const MachineFunction &Function, + const MachinePassContract &Contract) { + const MachineFunctionProperties Missing = Contract.Requires.missingFrom(Function.properties()); + if (!Missing.empty()) { + return makeUnexpected(ErrorCode::VerificationError, + "pass '" + Contract.Name + + "' requires properties: " + Missing.toString()); + } + return {}; +} + +[[nodiscard]] Error passFailure(std::string Message, + ErrorCode Code = ErrorCode::VerificationError) { + return Error(Code, std::move(Message)); +} + +[[nodiscard]] Error prefixedError(const Error &Source, std::string Prefix) { + Prefix.append(Source.message()); + return Error(Source.code(), std::move(Prefix)); +} + +[[nodiscard]] std::string_view legalizationActionName(LegalizationAction Action) noexcept { + switch (Action) { + case LegalizationAction::Legal: + return "legal"; + case LegalizationAction::Unsupported: + return "unsupported"; + case LegalizationAction::Custom: + return "custom"; + case LegalizationAction::Lower: + return "lower"; + case LegalizationAction::Libcall: + return "libcall"; + case LegalizationAction::WidenScalar: + return "widen-scalar"; + case LegalizationAction::NarrowScalar: + return "narrow-scalar"; + case LegalizationAction::MoreElements: + return "more-elements"; + case LegalizationAction::FewerElements: + return "fewer-elements"; + case LegalizationAction::Bitcast: + return "bitcast"; + case LegalizationAction::ChangeElementType: + return "change-element-type"; + case LegalizationAction::ChangeAddressSpace: + return "change-address-space"; + } + return "unknown"; +} + +[[nodiscard]] Expected clearTrackedLivenessFlags(MachineFunction &Function, + MachinePassResult &Result) { + if (!Result.Changed || !Function.properties().has(MachineFunctionProperty::TracksLiveness)) + return {}; + bool Changed = false; + for (MachineInstr *Instruction : layoutInstructions(Function)) { + for (std::size_t Index = 0; Index < Instruction->operandCount(); ++Index) { + MachineOperand &Operand = *Instruction->operandAt(Index); + if (!Operand.isRegister()) + continue; + RegisterOperandFlags Flags = Operand.registerFlags(); + if (!Flags.has(RegisterOperandFlag::Kill) && !Flags.has(RegisterOperandFlag::Dead)) + continue; + Flags.clear(RegisterOperandFlag::Kill); + Flags.clear(RegisterOperandFlag::Dead); + auto Updated = Operand.setRegisterFlags(Flags); + if (!Updated) + return std::unexpected(Updated.error()); + Changed = true; + } + } + if (Changed) + Result.Changes.add(MachinePassChange::Operands); + return {}; +} + +} // namespace + +const MachinePassContract &Legalizer::contract() const noexcept { + return legalizerContract(); +} + +Expected Legalizer::run(MachineFunction &Function, + const TargetDescription &Target, + MachineAnalysisManager &Analyses) { + if (Info == nullptr) + return std::unexpected( + passFailure("legalizer has no target behavior interface", ErrorCode::InvalidArgument)); + auto Required = requireProperties(Function, contract()); + if (!Required) + return std::unexpected(Required.error()); + + auto Trial = cloneMachineFunction( + Function, Target, + MachineFunctionCloneOptions{.NewStableID = Function.stableID(), .NewName = std::nullopt}); + if (!Trial) + return std::unexpected(prefixedError(Trial.error(), "legalizer transaction setup failed: ")); + MachineActionReplay Actions(Analyses, Trial->InstructionStableIDs); + auto TrialResult = runImplementation(*Trial->ClonedFunction, Target, Actions); + if (!TrialResult) + return std::unexpected(TrialResult.error()); + Actions.beginReplay(); + auto Result = runImplementation(Function, Target, Actions); + if (!Result) { + return std::unexpected(prefixedError( + Result.error(), "legalizer diverged after a successful transaction preflight: ")); + } + auto Replayed = Actions.finishReplay(); + if (!Replayed) + return std::unexpected(Replayed.error()); + return Result; +} + +Expected Legalizer::runImplementation(MachineFunction &Function, + const TargetDescription &Target, + MachineActionReplay &Actions) { + + MachinePassResult Result; + std::unordered_set SeenStates; + + std::vector Worklist = layoutInstructions(Function); + std::unordered_set PendingInstructions; + for (const MachineInstr *Instruction : Worklist) + PendingInstructions.insert(Instruction->stableID()); + for (std::size_t Index = 0; Index < Worklist.size(); ++Index) { + MachineInstr *Instruction = Worklist[Index]; + if (Instruction != nullptr) + PendingInstructions.erase(Instruction->stableID()); + if (Instruction == nullptr || Instruction->parent() == nullptr) + continue; + + const InstructionDescriptor *Descriptor = Target.instructionDescriptor(Instruction->opcode()); + if (Descriptor == nullptr) + return std::unexpected( + passFailure("legalizer encountered an unknown instruction descriptor")); + if (!Descriptor->Flags.has(InstructionFlag::Generic)) + continue; + + auto Validation = Target.validateInstruction(*Instruction, Function.registerInfo()); + if (!Validation) + return std::unexpected(prefixedError(Validation.error(), "legalizer input is invalid: ")); + + auto Action = Info->classify(*Instruction, Function, Target); + if (!Action) + return std::unexpected(Action.error()); + if (*Action == LegalizationAction::Legal) + continue; + if (*Action == LegalizationAction::Unsupported) { + return std::unexpected( + passFailure("target legalizer rejected generic instruction '" + Descriptor->Name + "'", + ErrorCode::Unsupported)); + } + + const OpcodeState Before = stateOf(*Instruction); + if (!SeenStates.insert(Before).second) + return std::unexpected( + passFailure("target legalizer entered a repeated state for '" + Descriptor->Name + "'", + ErrorCode::InternalError)); + + auto LoweringValidation = Info->validateLowering(*Instruction, Function, Target, *Action); + if (!LoweringValidation) + return std::unexpected( + prefixedError(LoweringValidation.error(), "legalizer lowering precondition failed: ")); + std::string Rule = "legalize."; + Rule.append(legalizationActionName(*Action)); + Rule.push_back('.'); + Rule.append(Descriptor->Name); + auto Accepted = Actions.request(Rule, Function, Instruction->stableID()); + if (!Accepted) + return std::unexpected(Accepted.error()); + if (!*Accepted) { + return std::unexpected( + passFailure("required legalizer action was rejected for '" + Descriptor->Name + "'", + ErrorCode::VerificationError)); + } + auto Lowered = Info->lower(*Instruction, Function, Target, *Action); + if (!Lowered) + return std::unexpected(Lowered.error()); + const bool InstructionWasErased = Instruction->parent() == nullptr; + if (!InstructionWasErased) { + const OpcodeState After = stateOf(*Instruction); + if (After == Before) + return std::unexpected(passFailure("target legalizer made no observable progress for '" + + Descriptor->Name + "'", + ErrorCode::InternalError)); + } + Result.Changed = true; + Result.Changes.add(MachinePassChange::Instructions); + + const std::vector Current = layoutInstructions(Function); + for (MachineInstr *Candidate : Current) { + const InstructionDescriptor *CandidateDescriptor = + Target.instructionDescriptor(Candidate->opcode()); + if (CandidateDescriptor == nullptr) + return std::unexpected(passFailure("legalizer produced an unknown instruction descriptor")); + if (CandidateDescriptor->Flags.has(InstructionFlag::Generic) && + PendingInstructions.insert(Candidate->stableID()).second) { + Worklist.push_back(Candidate); + } + } + } + + for (MachineInstr *Instruction : layoutInstructions(Function)) { + const InstructionDescriptor *Descriptor = Target.instructionDescriptor(Instruction->opcode()); + if (Descriptor == nullptr) + return std::unexpected(passFailure("legalizer produced an unknown instruction descriptor")); + if (!Descriptor->Flags.has(InstructionFlag::Generic)) + continue; + auto Action = Info->classify(*Instruction, Function, Target); + if (!Action) + return std::unexpected(Action.error()); + if (*Action != LegalizationAction::Legal) + return std::unexpected( + passFailure("legalizer reached a fixed point with an illegal generic instruction '" + + Descriptor->Name + "'", + *Action == LegalizationAction::Unsupported ? ErrorCode::Unsupported + : ErrorCode::InternalError)); + auto FinalValidation = Target.validateInstruction(*Instruction, Function.registerInfo()); + if (!FinalValidation) + return std::unexpected( + prefixedError(FinalValidation.error(), "legalizer produced invalid MachineIR: ")); + } + auto Liveness = clearTrackedLivenessFlags(Function, Result); + if (!Liveness) + return std::unexpected( + prefixedError(Liveness.error(), "legalizer liveness-flag invalidation failed: ")); + Result.Preserved = Result.Changed ? PreservedAnalyses::none() : PreservedAnalyses::all(); + return Result; +} + +} // namespace rcc diff --git a/backend/lib/CodeGen/GlobalISel/RegBankSelect.cpp b/backend/lib/CodeGen/GlobalISel/RegBankSelect.cpp new file mode 100644 index 0000000..337db80 --- /dev/null +++ b/backend/lib/CodeGen/GlobalISel/RegBankSelect.cpp @@ -0,0 +1,238 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "rcc/CodeGen/GlobalISel/RegBankSelect.h" + +#include "rcc/CodeGen/MachineBasicBlock.h" +#include "rcc/CodeGen/MachineFunction.h" +#include "rcc/CodeGen/MachineInstr.h" +#include "rcc/CodeGen/MachineLiveness.h" +#include "rcc/CodeGen/MachineRegisterInfo.h" +#include "rcc/CodeGen/TargetDescription.h" + +#include +#include +#include +#include +#include + +namespace rcc { +namespace { + +[[nodiscard]] const MachinePassContract &bankSelectContract() { + static const MachinePassContract Contract{ + .Name = "regbankselect", + .Requires = {MachineFunctionProperty::Legalized}, + .Sets = {MachineFunctionProperty::RegBankSelected}, + .Clears = {}, + .RequiredAnalyses = {}, + .VerificationStage = PipelineStage::RegBankSelected, + }; + return Contract; +} + +void combineFingerprint(std::uint64_t &State, std::uint64_t Value) noexcept { + State ^= Value + 0x9e3779b97f4a7c15ULL + (State << 6U) + (State >> 2U); +} + +[[nodiscard]] std::uint64_t +registerConfigurationFingerprint(const MachineRegisterInfo &RegInfo) noexcept { + std::uint64_t Result = 0xcbf29ce484222325ULL; + for (const VirtualRegisterInfo &Info : RegInfo.virtualRegisters()) { + combineFingerprint(Result, Info.IsTombstone ? 1U : 0U); + combineFingerprint(Result, Info.Bank ? Info.Bank->value() : 0U); + combineFingerprint(Result, Info.RegClass ? Info.RegClass->value() : 0U); + } + return Result; +} + +[[nodiscard]] std::vector layoutInstructions(MachineFunction &Function) { + std::vector Result; + for (MachineBasicBlock *Block = Function.firstBlock(); Block != nullptr; Block = Block->next()) + for (MachineInstr *Instruction = Block->firstInstruction(); Instruction != nullptr; + Instruction = Instruction->next()) + Result.push_back(Instruction); + return Result; +} + +[[nodiscard]] Expected requireProperties(const MachineFunction &Function, + const MachinePassContract &Contract) { + const MachineFunctionProperties Missing = Contract.Requires.missingFrom(Function.properties()); + if (!Missing.empty()) { + return makeUnexpected(ErrorCode::VerificationError, + "pass '" + Contract.Name + + "' requires properties: " + Missing.toString()); + } + return {}; +} + +[[nodiscard]] Expected restoreRegisterConfiguration( + MachineRegisterInfo &RegInfo, + const std::vector, + std::optional>>> &Snapshot) { + for (const auto &[Reg, Configuration] : Snapshot) { + auto ClearBank = RegInfo.clearRegisterBank(Reg); + if (!ClearBank) + return std::unexpected(ClearBank.error()); + if (Configuration.first) { + auto SetBank = RegInfo.setRegisterBank(Reg, *Configuration.first); + if (!SetBank) + return std::unexpected(SetBank.error()); + } + auto ClearClass = RegInfo.clearRegisterClass(Reg); + if (!ClearClass) + return std::unexpected(ClearClass.error()); + if (Configuration.second) { + auto SetClass = RegInfo.setRegisterClass(Reg, *Configuration.second); + if (!SetClass) + return std::unexpected(SetClass.error()); + } + } + return {}; +} + +[[nodiscard]] Error passFailure(std::string Message, + ErrorCode Code = ErrorCode::VerificationError) { + return Error(Code, std::move(Message)); +} + +[[nodiscard]] Error prefixedError(const Error &Source, std::string Prefix) { + Prefix.append(Source.message()); + return Error(Source.code(), std::move(Prefix)); +} + +[[nodiscard]] Expected repairTrackedLiveness(MachineFunction &Function, + const TargetDescription &Target, + MachinePassResult &Result) { + if (!Result.Changed || !Function.properties().has(MachineFunctionProperty::TracksLiveness)) { + return {}; + } + auto Rebuilt = rebuildMachineLiveness(Function, Target); + if (!Rebuilt) + return std::unexpected(Rebuilt.error()); + if (*Rebuilt) + Result.Changes.add(MachinePassChange::Operands); + return {}; +} + +} // namespace + +const MachinePassContract &RegBankSelect::contract() const noexcept { + return bankSelectContract(); +} + +Expected RegBankSelect::run(MachineFunction &Function, + const TargetDescription &Target, + MachineAnalysisManager &) { + if (Info == nullptr) + return std::unexpected(passFailure("register-bank select has no target behavior interface", + ErrorCode::InvalidArgument)); + auto Required = requireProperties(Function, contract()); + if (!Required) + return std::unexpected(Required.error()); + + MachinePassResult Result; + MachineRegisterInfo &RegInfo = Function.registerInfo(); + const std::uint64_t RegisterConfigurationBefore = registerConfigurationFingerprint(RegInfo); + using RegisterConfiguration = + std::pair, std::optional>; + std::vector> Snapshot; + std::vector> PlannedBanks; + for (std::size_t Index = 0; Index < RegInfo.virtualRegisters().size(); ++Index) { + auto Reg = Register::makeVirtual(Index); + if (!Reg) + return std::unexpected(Reg.error()); + const VirtualRegisterInfo &StoredInfo = RegInfo.virtualRegisters()[Index]; + if (StoredInfo.IsTombstone) + continue; + Snapshot.emplace_back(*Reg, RegisterConfiguration{StoredInfo.Bank, StoredInfo.RegClass}); + auto InfoResult = RegInfo.virtualRegisterInfo(*Reg); + if (!InfoResult) + return std::unexpected(InfoResult.error()); + const VirtualRegisterInfo &InfoValue = InfoResult->get(); + const MachineInstr *Context = nullptr; + for (const MachineOperand &Operand : RegInfo.regOperands(*Reg)) { + Context = Operand.parent(); + if (Context != nullptr) + break; + } + auto Bank = Info->selectBank(Function, *Reg, InfoValue, Context, Target); + if (!Bank) + return std::unexpected(Bank.error()); + if (Target.registers().registerBank(*Bank) == nullptr) + return std::unexpected(passFailure("target register-bank selector returned an unknown bank")); + if (InfoValue.Bank && *InfoValue.Bank != *Bank) + return std::unexpected( + passFailure("target register-bank selector conflicts with an existing bank")); + if (InfoValue.RegClass && !Target.registers().bankCoversClass(*Bank, *InfoValue.RegClass)) + return std::unexpected( + passFailure("existing register class is not covered by selected bank")); + PlannedBanks.emplace_back(*Reg, *Bank); + } + + for (MachineInstr *Instruction : layoutInstructions(Function)) { + auto Validation = Info->validateInstruction(*Instruction, Function, Target); + if (!Validation) + return std::unexpected( + prefixedError(Validation.error(), "register-bank mapping precondition failed: ")); + } + + for (const auto &[Reg, Bank] : PlannedBanks) { + const auto InfoResult = RegInfo.virtualRegisterInfo(Reg); + if (!InfoResult) + return std::unexpected(InfoResult.error()); + if (!InfoResult->get().Bank) { + auto SetBank = RegInfo.setRegisterBank(Reg, Bank); + if (!SetBank) + return std::unexpected(SetBank.error()); + Result.Changed = true; + Result.Changes.add(MachinePassChange::Registers); + } + } + + const auto Restore = [&]() -> Expected { + return restoreRegisterConfiguration(RegInfo, Snapshot); + }; + for (MachineInstr *Instruction : layoutInstructions(Function)) { + auto Constraint = Info->constrainInstruction(*Instruction, Function, Target); + if (!Constraint) { + auto Restored = Restore(); + if (!Restored) + return std::unexpected(prefixedError(Restored.error(), "register-bank rollback failed: ")); + return std::unexpected(Constraint.error()); + } + auto Validation = Target.validateInstruction(*Instruction, Function.registerInfo()); + if (!Validation) { + auto Restored = Restore(); + if (!Restored) + return std::unexpected(prefixedError(Restored.error(), "register-bank rollback failed: ")); + return std::unexpected(prefixedError(Validation.error(), + "register-bank selection produced invalid MachineIR: ")); + } + } + auto RegisterValidation = Target.validateRegisterInfo(RegInfo); + if (!RegisterValidation) { + auto Restored = Restore(); + if (!Restored) + return std::unexpected(prefixedError(Restored.error(), "register-bank rollback failed: ")); + return std::unexpected(prefixedError(RegisterValidation.error(), + "register-bank selection produced invalid registers: ")); + } + + if (registerConfigurationFingerprint(RegInfo) != RegisterConfigurationBefore) { + Result.Changed = true; + Result.Changes.add(MachinePassChange::Registers); + } + + auto Liveness = repairTrackedLiveness(Function, Target, Result); + if (!Liveness) { + auto Restored = Restore(); + if (!Restored) + return std::unexpected(prefixedError(Restored.error(), "register-bank rollback failed: ")); + return std::unexpected( + prefixedError(Liveness.error(), "register-bank liveness repair failed: ")); + } + Result.Preserved = Result.Changed ? PreservedAnalyses::none() : PreservedAnalyses::all(); + return Result; +} + +} // namespace rcc diff --git a/backend/lib/CodeGen/MachinePipelinePasses.cpp b/backend/lib/CodeGen/MachinePipelinePasses.cpp deleted file mode 100644 index 3dae07e..0000000 --- a/backend/lib/CodeGen/MachinePipelinePasses.cpp +++ /dev/null @@ -1,742 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later - -#include "rcc/CodeGen/MachinePipelinePasses.h" - -#include "rcc/CodeGen/GenericOpcodes.h" -#include "rcc/CodeGen/MachineBasicBlock.h" -#include "rcc/CodeGen/MachineFunction.h" -#include "rcc/CodeGen/MachineFunctionCloner.h" -#include "rcc/CodeGen/MachineInstr.h" -#include "rcc/CodeGen/MachineLiveness.h" -#include "rcc/CodeGen/MachineRegisterInfo.h" -#include "rcc/CodeGen/TargetDescription.h" - -#include -#include -#include -#include -#include -#include -#include - -namespace rcc { -namespace { - -[[nodiscard]] const MachinePassContract &legalizerContract() { - static const MachinePassContract Contract{ - .Name = "legalizer", - // LLVM's GlobalISel legalizer operates on SSA form and does not require - // the optional register-liveness tracking property. - .Requires = {MachineFunctionProperty::IsSSA}, - .Sets = {MachineFunctionProperty::Legalized}, - .Clears = {}, - .RequiredAnalyses = {}, - .VerificationStage = PipelineStage::Legalized, - }; - return Contract; -} - -[[nodiscard]] const MachinePassContract &bankSelectContract() { - static const MachinePassContract Contract{ - .Name = "regbankselect", - .Requires = {MachineFunctionProperty::Legalized}, - .Sets = {MachineFunctionProperty::RegBankSelected}, - .Clears = {}, - .RequiredAnalyses = {}, - .VerificationStage = PipelineStage::RegBankSelected, - }; - return Contract; -} - -[[nodiscard]] const MachinePassContract &instructionSelectContract() { - static const MachinePassContract Contract{ - .Name = "instruction-select", - .Requires = {MachineFunctionProperty::Legalized, MachineFunctionProperty::RegBankSelected}, - .Sets = {MachineFunctionProperty::Selected}, - .Clears = {}, - .RequiredAnalyses = {}, - .VerificationStage = PipelineStage::Selected, - }; - return Contract; -} - -struct OpcodeState final { - MachineInstrStableID Instruction; - Opcode OpcodeValue; - std::uint64_t OperandFingerprint = 0; - - friend bool operator==(const OpcodeState &Left, const OpcodeState &Right) noexcept = default; -}; - -struct OpcodeStateHash final { - [[nodiscard]] std::size_t operator()(const OpcodeState &State) const noexcept { - return std::hash{}(State.Instruction.value()) ^ - (std::hash{}(State.OpcodeValue.value()) << 1U) ^ - (std::hash{}(State.OperandFingerprint) << 2U); - } -}; - -void combineFingerprint(std::uint64_t &State, std::uint64_t Value) noexcept { - State ^= Value + 0x9e3779b97f4a7c15ULL + (State << 6U) + (State >> 2U); -} - -[[nodiscard]] std::uint64_t -registerConfigurationFingerprint(const MachineRegisterInfo &RegInfo) noexcept { - std::uint64_t Result = 0xcbf29ce484222325ULL; - for (const VirtualRegisterInfo &Info : RegInfo.virtualRegisters()) { - combineFingerprint(Result, Info.IsTombstone ? 1U : 0U); - combineFingerprint(Result, Info.Bank ? Info.Bank->value() : 0U); - combineFingerprint(Result, Info.RegClass ? Info.RegClass->value() : 0U); - } - return Result; -} - -[[nodiscard]] std::uint64_t operandFingerprint(const MachineInstr &Instruction) noexcept { - std::uint64_t Result = 0xcbf29ce484222325ULL; - combineFingerprint(Result, Instruction.flags().rawValue()); - combineFingerprint(Result, Instruction.operandCount()); - for (const MachineOperand &Operand : Instruction.operands()) { - combineFingerprint(Result, static_cast(Operand.kind())); - combineFingerprint(Result, Operand.targetFlags()); - combineFingerprint(Result, Operand.registerFlags().rawValue()); - combineFingerprint(Result, Operand.subReg().value()); - if (const Register *Reg = Operand.getIf()) - combineFingerprint(Result, Reg->opaqueValue()); - else if (const std::int64_t *Immediate = Operand.getIf()) - combineFingerprint(Result, static_cast(*Immediate)); - else if (const auto *Integer = Operand.getIf()) - combineFingerprint(Result, Integer->Value.bitWidth()); - else if (const auto *Floating = Operand.getIf()) - combineFingerprint(Result, static_cast(Floating->Bits.semantics())); - else if (const auto *Block = Operand.getIf()) - combineFingerprint(Result, Block->Block == nullptr ? 0 : Block->Block->stableID().value()); - } - return Result; -} - -[[nodiscard]] OpcodeState stateOf(const MachineInstr &Instruction) noexcept { - return {Instruction.stableID(), Instruction.opcode(), operandFingerprint(Instruction)}; -} - -[[nodiscard]] std::vector layoutInstructions(MachineFunction &Function) { - std::vector Result; - for (MachineBasicBlock *Block = Function.firstBlock(); Block != nullptr; Block = Block->next()) - for (MachineInstr *Instruction = Block->firstInstruction(); Instruction != nullptr; - Instruction = Instruction->next()) - Result.push_back(Instruction); - return Result; -} - -[[nodiscard]] std::vector stableCFGPostOrder(MachineFunction &Function) { - std::vector Roots; - for (MachineBasicBlock *Block = Function.firstBlock(); Block != nullptr; Block = Block->next()) - Roots.push_back(Block); - std::ranges::sort(Roots, {}, - [](const MachineBasicBlock *Block) { return Block->stableID().value(); }); - if (MachineBasicBlock *Entry = Function.firstBlock(); Entry != nullptr) { - const auto Position = std::ranges::find(Roots, Entry); - if (Position != Roots.end()) - std::rotate(Roots.begin(), Position, std::next(Position)); - } - - struct TraversalFrame final { - MachineBasicBlock *Block = nullptr; - std::vector Successors; - std::size_t NextSuccessor = 0; - }; - const auto MakeFrame = [](MachineBasicBlock &Block) { - TraversalFrame Frame; - Frame.Block = &Block; - for (const MachineSuccessor &Successor : Block.successors()) { - if (Successor.Block != nullptr) - Frame.Successors.push_back(Successor.Block); - } - std::ranges::sort(Frame.Successors, {}, [](const MachineBasicBlock *Successor) { - return Successor->stableID().value(); - }); - return Frame; - }; - - std::vector Result; - std::unordered_set Visited; - std::vector Stack; - for (MachineBasicBlock *Root : Roots) { - if (!Visited.insert(Root).second) - continue; - Stack.push_back(MakeFrame(*Root)); - while (!Stack.empty()) { - TraversalFrame &Frame = Stack.back(); - if (Frame.NextSuccessor < Frame.Successors.size()) { - MachineBasicBlock *Successor = Frame.Successors[Frame.NextSuccessor++]; - if (Visited.insert(Successor).second) - Stack.push_back(MakeFrame(*Successor)); - continue; - } - Result.push_back(Frame.Block); - Stack.pop_back(); - } - } - return Result; -} - -[[nodiscard]] std::vector bottomUpInstructions(MachineFunction &Function) { - std::vector Result; - for (MachineBasicBlock *Block : stableCFGPostOrder(Function)) { - for (MachineInstr *Instruction = Block->lastInstruction(); Instruction != nullptr; - Instruction = Instruction->previous()) - Result.push_back(Instruction); - } - return Result; -} - -[[nodiscard]] Expected requireProperties(const MachineFunction &Function, - const MachinePassContract &Contract) { - const MachineFunctionProperties Missing = Contract.Requires.missingFrom(Function.properties()); - if (!Missing.empty()) { - return makeUnexpected(ErrorCode::VerificationError, - "pass '" + Contract.Name + - "' requires properties: " + Missing.toString()); - } - return {}; -} - -[[nodiscard]] Expected restoreRegisterConfiguration( - MachineRegisterInfo &RegInfo, - const std::vector, - std::optional>>> &Snapshot) { - for (const auto &[Reg, Configuration] : Snapshot) { - auto ClearBank = RegInfo.clearRegisterBank(Reg); - if (!ClearBank) - return std::unexpected(ClearBank.error()); - if (Configuration.first) { - auto SetBank = RegInfo.setRegisterBank(Reg, *Configuration.first); - if (!SetBank) - return std::unexpected(SetBank.error()); - } - auto ClearClass = RegInfo.clearRegisterClass(Reg); - if (!ClearClass) - return std::unexpected(ClearClass.error()); - if (Configuration.second) { - auto SetClass = RegInfo.setRegisterClass(Reg, *Configuration.second); - if (!SetClass) - return std::unexpected(SetClass.error()); - } - } - return {}; -} - -[[nodiscard]] Error passFailure(std::string Message, - ErrorCode Code = ErrorCode::VerificationError) { - return Error(Code, std::move(Message)); -} - -[[nodiscard]] Error prefixedError(const Error &Source, std::string Prefix) { - Prefix.append(Source.message()); - return Error(Source.code(), std::move(Prefix)); -} - -[[nodiscard]] std::string_view legalizationActionName(LegalizationAction Action) noexcept { - switch (Action) { - case LegalizationAction::Legal: - return "legal"; - case LegalizationAction::Unsupported: - return "unsupported"; - case LegalizationAction::Custom: - return "custom"; - case LegalizationAction::Lower: - return "lower"; - case LegalizationAction::Libcall: - return "libcall"; - case LegalizationAction::WidenScalar: - return "widen-scalar"; - case LegalizationAction::NarrowScalar: - return "narrow-scalar"; - case LegalizationAction::MoreElements: - return "more-elements"; - case LegalizationAction::FewerElements: - return "fewer-elements"; - case LegalizationAction::Bitcast: - return "bitcast"; - case LegalizationAction::ChangeElementType: - return "change-element-type"; - case LegalizationAction::ChangeAddressSpace: - return "change-address-space"; - } - return "unknown"; -} - -[[nodiscard]] Expected repairTrackedLiveness(MachineFunction &Function, - const TargetDescription &Target, - MachinePassResult &Result) { - if (!Result.Changed || !Function.properties().has(MachineFunctionProperty::TracksLiveness)) { - return {}; - } - auto Rebuilt = rebuildMachineLiveness(Function, Target); - if (!Rebuilt) - return std::unexpected(Rebuilt.error()); - if (*Rebuilt) - Result.Changes.add(MachinePassChange::Operands); - return {}; -} - -[[nodiscard]] Expected clearTrackedLivenessFlags(MachineFunction &Function, - MachinePassResult &Result) { - if (!Result.Changed || !Function.properties().has(MachineFunctionProperty::TracksLiveness)) - return {}; - bool Changed = false; - for (MachineInstr *Instruction : layoutInstructions(Function)) { - for (std::size_t Index = 0; Index < Instruction->operandCount(); ++Index) { - MachineOperand &Operand = *Instruction->operandAt(Index); - if (!Operand.isRegister()) - continue; - RegisterOperandFlags Flags = Operand.registerFlags(); - if (!Flags.has(RegisterOperandFlag::Kill) && !Flags.has(RegisterOperandFlag::Dead)) - continue; - Flags.clear(RegisterOperandFlag::Kill); - Flags.clear(RegisterOperandFlag::Dead); - auto Updated = Operand.setRegisterFlags(Flags); - if (!Updated) - return std::unexpected(Updated.error()); - Changed = true; - } - } - if (Changed) - Result.Changes.add(MachinePassChange::Operands); - return {}; -} - -} // namespace - -const MachinePassContract &LegalizerPass::contract() const noexcept { - return legalizerContract(); -} - -Expected LegalizerPass::run(MachineFunction &Function, - const TargetDescription &Target, - MachineAnalysisManager &Analyses) { - if (Info == nullptr) - return std::unexpected( - passFailure("legalizer has no target behavior interface", ErrorCode::InvalidArgument)); - auto Required = requireProperties(Function, contract()); - if (!Required) - return std::unexpected(Required.error()); - - auto Trial = cloneMachineFunction( - Function, Target, - MachineFunctionCloneOptions{.NewStableID = Function.stableID(), .NewName = std::nullopt}); - if (!Trial) - return std::unexpected(prefixedError(Trial.error(), "legalizer transaction setup failed: ")); - MachineActionReplay Actions(Analyses, Trial->InstructionStableIDs); - auto TrialResult = runImplementation(*Trial->ClonedFunction, Target, Actions); - if (!TrialResult) - return std::unexpected(TrialResult.error()); - Actions.beginReplay(); - auto Result = runImplementation(Function, Target, Actions); - if (!Result) { - return std::unexpected(prefixedError( - Result.error(), "legalizer diverged after a successful transaction preflight: ")); - } - auto Replayed = Actions.finishReplay(); - if (!Replayed) - return std::unexpected(Replayed.error()); - return Result; -} - -Expected LegalizerPass::runImplementation(MachineFunction &Function, - const TargetDescription &Target, - MachineActionReplay &Actions) { - - MachinePassResult Result; - std::unordered_set SeenStates; - - std::vector Worklist = layoutInstructions(Function); - std::unordered_set PendingInstructions; - for (const MachineInstr *Instruction : Worklist) - PendingInstructions.insert(Instruction->stableID()); - for (std::size_t Index = 0; Index < Worklist.size(); ++Index) { - MachineInstr *Instruction = Worklist[Index]; - if (Instruction != nullptr) - PendingInstructions.erase(Instruction->stableID()); - if (Instruction == nullptr || Instruction->parent() == nullptr) - continue; - - const InstructionDescriptor *Descriptor = Target.instructionDescriptor(Instruction->opcode()); - if (Descriptor == nullptr) - return std::unexpected( - passFailure("legalizer encountered an unknown instruction descriptor")); - if (!Descriptor->Flags.has(InstructionFlag::Generic)) - continue; - - auto Validation = Target.validateInstruction(*Instruction, Function.registerInfo()); - if (!Validation) - return std::unexpected(prefixedError(Validation.error(), "legalizer input is invalid: ")); - - auto Action = Info->classify(*Instruction, Function, Target); - if (!Action) - return std::unexpected(Action.error()); - if (*Action == LegalizationAction::Legal) - continue; - if (*Action == LegalizationAction::Unsupported) { - return std::unexpected( - passFailure("target legalizer rejected generic instruction '" + Descriptor->Name + "'", - ErrorCode::Unsupported)); - } - - const OpcodeState Before = stateOf(*Instruction); - if (!SeenStates.insert(Before).second) - return std::unexpected( - passFailure("target legalizer entered a repeated state for '" + Descriptor->Name + "'", - ErrorCode::InternalError)); - - auto LoweringValidation = Info->validateLowering(*Instruction, Function, Target, *Action); - if (!LoweringValidation) - return std::unexpected( - prefixedError(LoweringValidation.error(), "legalizer lowering precondition failed: ")); - std::string Rule = "legalize."; - Rule.append(legalizationActionName(*Action)); - Rule.push_back('.'); - Rule.append(Descriptor->Name); - auto Accepted = Actions.request(Rule, Function, Instruction->stableID()); - if (!Accepted) - return std::unexpected(Accepted.error()); - if (!*Accepted) { - return std::unexpected( - passFailure("required legalizer action was rejected for '" + Descriptor->Name + "'", - ErrorCode::VerificationError)); - } - auto Lowered = Info->lower(*Instruction, Function, Target, *Action); - if (!Lowered) - return std::unexpected(Lowered.error()); - const bool InstructionWasErased = Instruction->parent() == nullptr; - if (!InstructionWasErased) { - const OpcodeState After = stateOf(*Instruction); - if (After == Before) - return std::unexpected(passFailure("target legalizer made no observable progress for '" + - Descriptor->Name + "'", - ErrorCode::InternalError)); - } - Result.Changed = true; - Result.Changes.add(MachinePassChange::Instructions); - - const std::vector Current = layoutInstructions(Function); - for (MachineInstr *Candidate : Current) { - const InstructionDescriptor *CandidateDescriptor = - Target.instructionDescriptor(Candidate->opcode()); - if (CandidateDescriptor == nullptr) - return std::unexpected(passFailure("legalizer produced an unknown instruction descriptor")); - if (CandidateDescriptor->Flags.has(InstructionFlag::Generic) && - PendingInstructions.insert(Candidate->stableID()).second) { - Worklist.push_back(Candidate); - } - } - } - - for (MachineInstr *Instruction : layoutInstructions(Function)) { - const InstructionDescriptor *Descriptor = Target.instructionDescriptor(Instruction->opcode()); - if (Descriptor == nullptr) - return std::unexpected(passFailure("legalizer produced an unknown instruction descriptor")); - if (!Descriptor->Flags.has(InstructionFlag::Generic)) - continue; - auto Action = Info->classify(*Instruction, Function, Target); - if (!Action) - return std::unexpected(Action.error()); - if (*Action != LegalizationAction::Legal) - return std::unexpected( - passFailure("legalizer reached a fixed point with an illegal generic instruction '" + - Descriptor->Name + "'", - *Action == LegalizationAction::Unsupported ? ErrorCode::Unsupported - : ErrorCode::InternalError)); - auto FinalValidation = Target.validateInstruction(*Instruction, Function.registerInfo()); - if (!FinalValidation) - return std::unexpected( - prefixedError(FinalValidation.error(), "legalizer produced invalid MachineIR: ")); - } - auto Liveness = clearTrackedLivenessFlags(Function, Result); - if (!Liveness) - return std::unexpected( - prefixedError(Liveness.error(), "legalizer liveness-flag invalidation failed: ")); - Result.Preserved = Result.Changed ? PreservedAnalyses::none() : PreservedAnalyses::all(); - return Result; -} - -const MachinePassContract &RegisterBankSelectPass::contract() const noexcept { - return bankSelectContract(); -} - -Expected RegisterBankSelectPass::run(MachineFunction &Function, - const TargetDescription &Target, - MachineAnalysisManager &) { - if (Info == nullptr) - return std::unexpected(passFailure("register-bank select has no target behavior interface", - ErrorCode::InvalidArgument)); - auto Required = requireProperties(Function, contract()); - if (!Required) - return std::unexpected(Required.error()); - - MachinePassResult Result; - MachineRegisterInfo &RegInfo = Function.registerInfo(); - const std::uint64_t RegisterConfigurationBefore = registerConfigurationFingerprint(RegInfo); - using RegisterConfiguration = - std::pair, std::optional>; - std::vector> Snapshot; - std::vector> PlannedBanks; - for (std::size_t Index = 0; Index < RegInfo.virtualRegisters().size(); ++Index) { - auto Reg = Register::makeVirtual(Index); - if (!Reg) - return std::unexpected(Reg.error()); - const VirtualRegisterInfo &StoredInfo = RegInfo.virtualRegisters()[Index]; - if (StoredInfo.IsTombstone) - continue; - Snapshot.emplace_back(*Reg, RegisterConfiguration{StoredInfo.Bank, StoredInfo.RegClass}); - auto InfoResult = RegInfo.virtualRegisterInfo(*Reg); - if (!InfoResult) - return std::unexpected(InfoResult.error()); - const VirtualRegisterInfo &InfoValue = InfoResult->get(); - const MachineInstr *Context = nullptr; - for (const MachineOperand &Operand : RegInfo.regOperands(*Reg)) { - Context = Operand.parent(); - if (Context != nullptr) - break; - } - auto Bank = Info->selectBank(Function, *Reg, InfoValue, Context, Target); - if (!Bank) - return std::unexpected(Bank.error()); - if (Target.registers().registerBank(*Bank) == nullptr) - return std::unexpected(passFailure("target register-bank selector returned an unknown bank")); - if (InfoValue.Bank && *InfoValue.Bank != *Bank) - return std::unexpected( - passFailure("target register-bank selector conflicts with an existing bank")); - if (InfoValue.RegClass && !Target.registers().bankCoversClass(*Bank, *InfoValue.RegClass)) - return std::unexpected( - passFailure("existing register class is not covered by selected bank")); - PlannedBanks.emplace_back(*Reg, *Bank); - } - - for (MachineInstr *Instruction : layoutInstructions(Function)) { - auto Validation = Info->validateInstruction(*Instruction, Function, Target); - if (!Validation) - return std::unexpected( - prefixedError(Validation.error(), "register-bank mapping precondition failed: ")); - } - - for (const auto &[Reg, Bank] : PlannedBanks) { - const auto InfoResult = RegInfo.virtualRegisterInfo(Reg); - if (!InfoResult) - return std::unexpected(InfoResult.error()); - if (!InfoResult->get().Bank) { - auto SetBank = RegInfo.setRegisterBank(Reg, Bank); - if (!SetBank) - return std::unexpected(SetBank.error()); - Result.Changed = true; - Result.Changes.add(MachinePassChange::Registers); - } - } - - const auto Restore = [&]() -> Expected { - return restoreRegisterConfiguration(RegInfo, Snapshot); - }; - for (MachineInstr *Instruction : layoutInstructions(Function)) { - auto Constraint = Info->constrainInstruction(*Instruction, Function, Target); - if (!Constraint) { - auto Restored = Restore(); - if (!Restored) - return std::unexpected(prefixedError(Restored.error(), "register-bank rollback failed: ")); - return std::unexpected(Constraint.error()); - } - auto Validation = Target.validateInstruction(*Instruction, Function.registerInfo()); - if (!Validation) { - auto Restored = Restore(); - if (!Restored) - return std::unexpected(prefixedError(Restored.error(), "register-bank rollback failed: ")); - return std::unexpected(prefixedError(Validation.error(), - "register-bank selection produced invalid MachineIR: ")); - } - } - auto RegisterValidation = Target.validateRegisterInfo(RegInfo); - if (!RegisterValidation) { - auto Restored = Restore(); - if (!Restored) - return std::unexpected(prefixedError(Restored.error(), "register-bank rollback failed: ")); - return std::unexpected(prefixedError(RegisterValidation.error(), - "register-bank selection produced invalid registers: ")); - } - - if (registerConfigurationFingerprint(RegInfo) != RegisterConfigurationBefore) { - Result.Changed = true; - Result.Changes.add(MachinePassChange::Registers); - } - - auto Liveness = repairTrackedLiveness(Function, Target, Result); - if (!Liveness) { - auto Restored = Restore(); - if (!Restored) - return std::unexpected(prefixedError(Restored.error(), "register-bank rollback failed: ")); - return std::unexpected( - prefixedError(Liveness.error(), "register-bank liveness repair failed: ")); - } - Result.Preserved = Result.Changed ? PreservedAnalyses::none() : PreservedAnalyses::all(); - return Result; -} - -const MachinePassContract &InstructionSelectPass::contract() const noexcept { - return instructionSelectContract(); -} - -Expected InstructionSelectPass::run(MachineFunction &Function, - const TargetDescription &Target, - MachineAnalysisManager &Analyses) { - if (Info == nullptr) - return std::unexpected(passFailure("instruction select has no target behavior interface", - ErrorCode::InvalidArgument)); - auto Required = requireProperties(Function, contract()); - if (!Required) - return std::unexpected(Required.error()); - - auto Trial = cloneMachineFunction( - Function, Target, - MachineFunctionCloneOptions{.NewStableID = Function.stableID(), .NewName = std::nullopt}); - if (!Trial) { - return std::unexpected( - prefixedError(Trial.error(), "instruction-selection transaction setup failed: ")); - } - MachineActionReplay Actions(Analyses, Trial->InstructionStableIDs); - auto TrialResult = runImplementation(*Trial->ClonedFunction, Target, Actions); - if (!TrialResult) - return std::unexpected(TrialResult.error()); - Actions.beginReplay(); - auto Result = runImplementation(Function, Target, Actions); - if (!Result) { - return std::unexpected( - prefixedError(Result.error(), - "instruction selection diverged after a successful transaction preflight: ")); - } - auto Replayed = Actions.finishReplay(); - if (!Replayed) - return std::unexpected(Replayed.error()); - return Result; -} - -Expected -InstructionSelectPass::runImplementation(MachineFunction &Function, const TargetDescription &Target, - MachineActionReplay &Actions) { - - MachinePassResult Result; - std::vector Worklist; - std::unordered_set DiscoveredInstructions; - std::unordered_set SeenStates; - for (MachineInstr *Instruction : bottomUpInstructions(Function)) { - const InstructionDescriptor *Descriptor = Target.instructionDescriptor(Instruction->opcode()); - if (Descriptor == nullptr) - return std::unexpected( - passFailure("instruction selector encountered an unknown instruction descriptor")); - auto Validation = Target.validateInstruction(*Instruction, Function.registerInfo()); - if (!Validation) - return std::unexpected( - prefixedError(Validation.error(), "instruction selector input is invalid: ")); - if (!Descriptor->Flags.has(InstructionFlag::Generic)) - continue; - auto Match = Info->canSelect(*Instruction, Function, Target); - if (!Match) - return std::unexpected(Match.error()); - Worklist.push_back(Instruction); - DiscoveredInstructions.insert(Instruction->stableID()); - } - - for (std::size_t Index = 0; Index < Worklist.size(); ++Index) { - MachineInstr *Instruction = Worklist[Index]; - if (Instruction->parent() == nullptr) - return std::unexpected(passFailure("instruction selector lost its input instruction")); - const InstructionDescriptor *CurrentDescriptor = - Target.instructionDescriptor(Instruction->opcode()); - if (CurrentDescriptor == nullptr) - return std::unexpected( - passFailure("instruction selector encountered an unknown instruction descriptor")); - if (!CurrentDescriptor->Flags.has(InstructionFlag::Generic)) - continue; - const OpcodeState Before = stateOf(*Instruction); - if (!SeenStates.insert(Before).second) { - return std::unexpected(passFailure("instruction selector entered a repeated state for '" + - CurrentDescriptor->Name + "'", - ErrorCode::InternalError)); - } - auto Match = Info->canSelect(*Instruction, Function, Target); - if (!Match) - return std::unexpected(Match.error()); - std::string Rule = "select."; - Rule.append(CurrentDescriptor->Name); - auto Accepted = Actions.request(Rule, Function, Instruction->stableID()); - if (!Accepted) - return std::unexpected(Accepted.error()); - if (!*Accepted) { - return std::unexpected(passFailure("required selection action was rejected for '" + - CurrentDescriptor->Name + "'", - ErrorCode::VerificationError)); - } - auto Selection = Info->select(*Instruction, Function, Target); - if (!Selection) - return std::unexpected(Selection.error()); - const InstructionDescriptor *Selected = Target.instructionDescriptor(Instruction->opcode()); - if (Selected == nullptr) - return std::unexpected( - passFailure("instruction selector produced an unknown instruction descriptor")); - auto Constraint = Info->constrainSelectedInstruction(*Instruction, Function, Target); - if (!Constraint) { - return std::unexpected(prefixedError( - Constraint.error(), "instruction selector could not constrain selected registers: ")); - } - auto Validation = Target.validateInstruction(*Instruction, Function.registerInfo()); - if (!Validation) - return std::unexpected( - prefixedError(Validation.error(), "instruction selector produced invalid MachineIR: ")); - const OpcodeState After = stateOf(*Instruction); - if (After == Before) - return std::unexpected( - passFailure("instruction selector reported success without observable progress", - ErrorCode::InternalError)); - Result.Changed = true; - Result.Changes.add(MachinePassChange::Instructions); - if (Selected->Flags.has(InstructionFlag::Generic)) - Worklist.push_back(Instruction); - for (MachineInstr *Candidate : bottomUpInstructions(Function)) { - const InstructionDescriptor *CandidateDescriptor = - Target.instructionDescriptor(Candidate->opcode()); - if (CandidateDescriptor == nullptr) - return std::unexpected( - passFailure("instruction selector produced an unknown instruction descriptor")); - if (!CandidateDescriptor->Flags.has(InstructionFlag::Generic) || - !DiscoveredInstructions.insert(Candidate->stableID()).second) { - continue; - } - auto CandidateMatch = Info->canSelect(*Candidate, Function, Target); - if (!CandidateMatch) - return std::unexpected(CandidateMatch.error()); - Worklist.push_back(Candidate); - } - } - for (MachineInstr *Instruction : layoutInstructions(Function)) { - const InstructionDescriptor *Descriptor = Target.instructionDescriptor(Instruction->opcode()); - if (Descriptor == nullptr) - return std::unexpected( - passFailure("instruction selector produced an unknown instruction descriptor")); - auto Validation = Target.validateInstruction(*Instruction, Function.registerInfo()); - if (!Validation) - return std::unexpected( - prefixedError(Validation.error(), "instruction selector produced invalid MachineIR: ")); - if (Descriptor->Flags.has(InstructionFlag::Generic)) - return std::unexpected( - passFailure("instruction selector left a generic opcode in the function")); - } - auto RegisterValidation = Target.validateRegisterInfo(Function.registerInfo()); - if (!RegisterValidation) - return std::unexpected(prefixedError(RegisterValidation.error(), - "instruction selection produced invalid registers: ")); - auto Liveness = repairTrackedLiveness(Function, Target, Result); - if (!Liveness) { - return std::unexpected( - prefixedError(Liveness.error(), "instruction-selection liveness repair failed: ")); - } - Result.Preserved = Result.Changed ? PreservedAnalyses::none() : PreservedAnalyses::all(); - return Result; -} - -} // namespace rcc diff --git a/backend/lib/Target/RISCV/RISCVCodeGen.cpp b/backend/lib/Target/RISCV/RISCVCodeGen.cpp index 00dba94..b610d81 100644 --- a/backend/lib/Target/RISCV/RISCVCodeGen.cpp +++ b/backend/lib/Target/RISCV/RISCVCodeGen.cpp @@ -3250,7 +3250,7 @@ struct VACopyPlan final { return eraseInstruction(Instruction); } -class RISCVLegalizerInfo final : public TargetLegalizerInfo { +class RISCVLegalizerInfo final : public LegalizerInfo { public: explicit RISCVLegalizerInfo(RISCVSubtargetFeatures Features) : Features(Features) {} @@ -3985,7 +3985,7 @@ private: RISCVSubtargetFeatures Features; }; -class RISCVRegisterBankInfo final : public TargetRegisterBankInfo { +class RISCVRegisterBankInfo final : public RegisterBankInfo { public: [[nodiscard]] Expected selectBank(const MachineFunction &, Register, const VirtualRegisterInfo &Info, @@ -4049,7 +4049,7 @@ public: } }; -class RISCVInstructionSelector final : public TargetInstructionSelector { +class RISCVInstructionSelector final : public InstructionSelector { public: [[nodiscard]] Expected constrainSelectedInstruction(MachineInstr &Instruction, MachineFunction &Function, @@ -6514,21 +6514,21 @@ private: } // namespace -const TargetLegalizerInfo &legalizerInfo() noexcept { +const LegalizerInfo &legalizerInfo() noexcept { static const RISCVLegalizerInfo Value(RISCVSubtargetFeatures::rv64gc()); return Value; } -std::unique_ptr createLegalizerInfo(RISCVSubtargetFeatures Features) { +std::unique_ptr createLegalizerInfo(RISCVSubtargetFeatures Features) { return std::make_unique(Features); } -const TargetRegisterBankInfo ®isterBankInfo() noexcept { +const RegisterBankInfo ®isterBankInfo() noexcept { static const RISCVRegisterBankInfo Value; return Value; } -const TargetInstructionSelector &instructionSelector() noexcept { +const InstructionSelector &instructionSelector() noexcept { static const RISCVInstructionSelector Value; return Value; } diff --git a/backend/lib/Target/RISCV/RISCVPipeline.cpp b/backend/lib/Target/RISCV/RISCVPipeline.cpp index 08a4653..7c778ea 100644 --- a/backend/lib/Target/RISCV/RISCVPipeline.cpp +++ b/backend/lib/Target/RISCV/RISCVPipeline.cpp @@ -3,10 +3,12 @@ #include "rcc/Target/RISCV/RISCVPipeline.h" #include "RISCVInstrInfo.h" +#include "rcc/CodeGen/GlobalISel/InstructionSelect.h" +#include "rcc/CodeGen/GlobalISel/Legalizer.h" +#include "rcc/CodeGen/GlobalISel/RegBankSelect.h" #include "rcc/CodeGen/MachineCombiner.h" #include "rcc/CodeGen/MachineFunction.h" #include "rcc/CodeGen/MachineOptimizationPipeline.h" -#include "rcc/CodeGen/MachinePipelinePasses.h" #include "rcc/CodeGen/MachineSSAExit.h" #include "rcc/CodeGen/RegAllocPBQP.h" #include "rcc/CodeGen/TargetDescription.h" @@ -33,13 +35,13 @@ template MachineCombinerStage::PreLegalizer); if (!Added) return std::unexpected(Added.error()); - Added = addPass(Pipeline, createLegalizerInfo(Features)); + Added = addPass(Pipeline, createLegalizerInfo(Features)); if (!Added) return std::unexpected(Added.error()); - Added = addPass(Pipeline, registerBankInfo()); + Added = addPass(Pipeline, registerBankInfo()); if (!Added) return std::unexpected(Added.error()); - return addPass(Pipeline, instructionSelector()); + return addPass(Pipeline, instructionSelector()); } [[nodiscard]] Expected addSSAExitPipeline(MachinePassManager &Pipeline) { @@ -86,17 +88,17 @@ Expected addCanonicalPipeline(MachinePassManager &Pipeline, const MachineF MachineCombinerStage::PreLegalizer); if (!Added) return std::unexpected(Added.error()); - Added = addPass(Pipeline, createLegalizerInfo(Features)); + Added = addPass(Pipeline, createLegalizerInfo(Features)); if (!Added) return std::unexpected(Added.error()); } if (!Function.properties().has(MachineFunctionProperty::RegBankSelected)) { - auto Added = addPass(Pipeline, registerBankInfo()); + auto Added = addPass(Pipeline, registerBankInfo()); if (!Added) return std::unexpected(Added.error()); } if (!Function.properties().has(MachineFunctionProperty::Selected)) { - auto Added = addPass(Pipeline, instructionSelector()); + auto Added = addPass(Pipeline, instructionSelector()); if (!Added) return std::unexpected(Added.error()); } -- cgit v1.2.3