From 2920d4547d2ccea40da547de5d07dd2383de5e87 Mon Sep 17 00:00:00 2001 From: Richard-Qin-X Date: Wed, 19 Aug 2026 18:13:19 +0800 Subject: [CodeGen] Remove RCC fallthrough normalization --- backend/include/rcc/CodeGen/MachineFallthrough.h | 27 ---- backend/lib/CodeGen/CMakeLists.txt | 2 - backend/lib/CodeGen/MachineFallthrough.cpp | 163 --------------------- .../lib/CodeGen/MachineOptimizationPipeline.cpp | 4 - backend/unittests/Target/RISCVLateCodeGenTest.cpp | 74 ---------- 5 files changed, 270 deletions(-) delete mode 100644 backend/include/rcc/CodeGen/MachineFallthrough.h delete mode 100644 backend/lib/CodeGen/MachineFallthrough.cpp (limited to 'backend') diff --git a/backend/include/rcc/CodeGen/MachineFallthrough.h b/backend/include/rcc/CodeGen/MachineFallthrough.h deleted file mode 100644 index bb62e8a..0000000 --- a/backend/include/rcc/CodeGen/MachineFallthrough.h +++ /dev/null @@ -1,27 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later - -#ifndef RCC_CODEGEN_MACHINEFALLTHROUGH_H -#define RCC_CODEGEN_MACHINEFALLTHROUGH_H - -#include "rcc/CodeGen/MachinePassManager.h" - -namespace rcc { - -class TargetInstrInfo; - -class MachineFallthroughPass final : public MachineFunctionPass { -public: - explicit MachineFallthroughPass(const TargetInstrInfo &Info) noexcept : Info(&Info) {} - - [[nodiscard]] const MachinePassContract &contract() const noexcept override; - [[nodiscard]] Expected run(MachineFunction &Function, - const TargetDescription &Target, - MachineFunctionAnalysisManager &Analyses) override; - -private: - const TargetInstrInfo *Info; -}; - -} // namespace rcc - -#endif // RCC_CODEGEN_MACHINEFALLTHROUGH_H diff --git a/backend/lib/CodeGen/CMakeLists.txt b/backend/lib/CodeGen/CMakeLists.txt index 881e17e..6a7f38d 100644 --- a/backend/lib/CodeGen/CMakeLists.txt +++ b/backend/lib/CodeGen/CMakeLists.txt @@ -25,7 +25,6 @@ set( MachineDebugInfo.cpp MachineDCE.cpp MachineFrameInfo.cpp - MachineFallthrough.cpp MachineFinalization.cpp MachineFunction.cpp MachineFunctionAttributes.cpp @@ -112,7 +111,6 @@ set( "${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/MachineDebugInfo.h" "${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/MachineDCE.h" "${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/MachineFrameInfo.h" - "${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/MachineFallthrough.h" "${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/MachineFinalization.h" "${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/MachineFunction.h" "${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/MachineFunctionAttributes.h" diff --git a/backend/lib/CodeGen/MachineFallthrough.cpp b/backend/lib/CodeGen/MachineFallthrough.cpp deleted file mode 100644 index 3619155..0000000 --- a/backend/lib/CodeGen/MachineFallthrough.cpp +++ /dev/null @@ -1,163 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later - -#include "rcc/CodeGen/MachineFallthrough.h" - -#include "rcc/CodeGen/LivePhysRegs.h" -#include "rcc/CodeGen/LiveVariables.h" -#include "rcc/CodeGen/MachineBasicBlock.h" -#include "rcc/CodeGen/MachineFunction.h" -#include "rcc/CodeGen/MachineFunctionCloner.h" -#include "rcc/CodeGen/TargetDescription.h" -#include "rcc/CodeGen/TargetInstrInfo.h" - -#include -#include -#include -#include - -namespace rcc { -namespace { - -[[nodiscard]] const MachinePassContract &fallthroughContract() { - static const MachinePassContract Contract = [] { - MachinePassContract Value{ - .Name = "machine-fallthrough-normalization", - .Requires = {MachineFunctionProperty::Selected, MachineFunctionProperty::NoPHIs, - MachineFunctionProperty::NoVRegs, MachineFunctionProperty::TracksLiveness}, - .Sets = {}, - .Clears = {}, - .RequiredAnalyses = {MachineFunctionAnalysisManager::id()}, - .VerificationStage = PipelineStage::RegisterAllocated, - }; - Value.ThreadSafety = PassThreadSafety::ThreadSafe; - Value.DeclaredChanges = {MachinePassChange::Instructions, MachinePassChange::Operands}; - return Value; - }(); - return Contract; -} - -[[nodiscard]] Expected> -normalizeFallthroughs(MachineFunction &Function, const TargetDescription &Target, - const TargetInstrInfo &Info) { - std::vector ChangedBlocks; - for (MachineBasicBlock *Block = Function.firstBlock(); Block != nullptr; Block = Block->next()) { - MachineBasicBlock *LayoutSuccessor = Block->next(); - if (LayoutSuccessor == nullptr) - continue; - auto Analysis = Info.analyzeBranch(*Block, Function, Target); - if (!Analysis) - return std::unexpected(Analysis.error()); - if (Analysis->HasUnanalyzableTerminator) - continue; - bool Changed = false; - if (Analysis->Conditional != nullptr && Analysis->Unconditional != nullptr && - Analysis->FalseTarget == LayoutSuccessor) { - auto Removed = Info.removeBranch(*Analysis->Unconditional, Function, Target); - if (!Removed) - return std::unexpected(Removed.error()); - Changed = true; - } else if (Analysis->Conditional != nullptr && Analysis->Unconditional != nullptr && - Analysis->TrueTarget == LayoutSuccessor && Analysis->FalseTarget != nullptr) { - auto Reversed = Info.reverseBranchCondition(*Analysis->Conditional, *Analysis->FalseTarget, - Function, Target); - if (!Reversed) - return std::unexpected(Reversed.error()); - auto Removed = Info.removeBranch(*Analysis->Unconditional, Function, Target); - if (!Removed) - return std::unexpected(Removed.error()); - Changed = true; - } else if (Analysis->Conditional != nullptr && Analysis->Unconditional == nullptr && - Analysis->FalseTarget == LayoutSuccessor) { - continue; - } else if (Analysis->Conditional != nullptr && Analysis->Unconditional == nullptr && - Analysis->TrueTarget == LayoutSuccessor && Analysis->FalseTarget != nullptr) { - auto Reversed = Info.reverseBranchCondition(*Analysis->Conditional, *Analysis->FalseTarget, - Function, Target); - if (!Reversed) - return std::unexpected(Reversed.error()); - Changed = true; - } else if (Analysis->Conditional != nullptr && Analysis->Unconditional == nullptr && - Analysis->FalseTarget != nullptr) { - auto Inserted = Info.insertBranch(*Block, *Analysis->FalseTarget, Function, Target); - if (!Inserted) - return std::unexpected(Inserted.error()); - Changed = true; - } else if (Analysis->Conditional == nullptr && Analysis->Unconditional != nullptr && - Analysis->TrueTarget == LayoutSuccessor) { - auto Removed = Info.removeBranch(*Analysis->Unconditional, Function, Target); - if (!Removed) - return std::unexpected(Removed.error()); - Changed = true; - } else if (Analysis->Conditional == nullptr && Analysis->Unconditional == nullptr && - Block->successors().size() == 1 && - Block->successors().front().Block != LayoutSuccessor) { - MachineBasicBlock *Successor = Block->successors().front().Block; - if (Successor == nullptr) { - return makeUnexpected(ErrorCode::VerificationError, - "fallthrough normalization encountered a null successor"); - } - auto Inserted = Info.insertBranch(*Block, *Successor, Function, Target); - if (!Inserted) - return std::unexpected(Inserted.error()); - Changed = true; - } - if (Changed) - ChangedBlocks.push_back(Block); - } - return ChangedBlocks; -} - -} // namespace - -const MachinePassContract &MachineFallthroughPass::contract() const noexcept { - return fallthroughContract(); -} - -Expected MachineFallthroughPass::run(MachineFunction &Function, - const TargetDescription &Target, - MachineFunctionAnalysisManager &Analyses) { - if (!Function.properties().containsAll(contract().Requires)) { - return makeUnexpected(ErrorCode::VerificationError, - "fallthrough normalization requires allocated tracked-liveness MIR"); - } - auto Trial = cloneMachineFunction( - Function, Target, - MachineFunctionCloneOptions{.NewStableID = Function.stableID(), .NewName = std::nullopt}); - if (!Trial) - return std::unexpected(withErrorContext(Trial.error(), "fallthrough setup failed: ")); - MachineFunctionAnalysisManager TrialAnalyses; - auto TrialLiveness = - TrialAnalyses.getResult(*Trial->ClonedFunction, Target); - if (!TrialLiveness) - return std::unexpected(TrialLiveness.error()); - auto TrialChanged = normalizeFallthroughs(*Trial->ClonedFunction, Target, *Info); - if (!TrialChanged) - return std::unexpected(TrialChanged.error()); - auto TrialRepair = repairPostRAMachineBlockLiveness(*TrialChanged, Target, **TrialLiveness); - if (!TrialRepair) - return std::unexpected(TrialRepair.error()); - - auto Liveness = Analyses.getResult(Function, Target); - if (!Liveness) - return std::unexpected(Liveness.error()); - auto ChangedBlocks = normalizeFallthroughs(Function, Target, *Info); - if (!ChangedBlocks) { - return std::unexpected(withErrorContext(ChangedBlocks.error(), - "fallthrough diverged after a successful preflight: ")); - } - auto Repaired = repairPostRAMachineBlockLiveness(*ChangedBlocks, Target, **Liveness); - if (!Repaired) - return std::unexpected(Repaired.error()); - - MachinePassResult Result; - Result.Changed = !ChangedBlocks->empty() || *Repaired; - if (Result.Changed) { - Result.Changes = {MachinePassChange::Instructions, MachinePassChange::Operands}; - Result.Preserved.preserve(); - } else { - Result.Preserved = PreservedAnalyses::all(); - } - return Result; -} - -} // namespace rcc diff --git a/backend/lib/CodeGen/MachineOptimizationPipeline.cpp b/backend/lib/CodeGen/MachineOptimizationPipeline.cpp index 7634ecd..f96d544 100644 --- a/backend/lib/CodeGen/MachineOptimizationPipeline.cpp +++ b/backend/lib/CodeGen/MachineOptimizationPipeline.cpp @@ -11,7 +11,6 @@ #include "rcc/CodeGen/MachineCombiner.h" #include "rcc/CodeGen/MachineCopyPropagation.h" #include "rcc/CodeGen/MachineDCE.h" -#include "rcc/CodeGen/MachineFallthrough.h" #include "rcc/CodeGen/MachineFinalization.h" #include "rcc/CodeGen/MachineLICM.h" #include "rcc/CodeGen/MachineMemoryFolding.h" @@ -117,9 +116,6 @@ addPostRegisterAllocationPipeline(MachineFunctionPassManager &Pipeline, if (!Added) return std::unexpected(Added.error()); Added = addPass(Pipeline); - if (!Added) - return std::unexpected(Added.error()); - Added = addPass(Pipeline, TargetInfo.InstrInfo); if (!Added) return std::unexpected(Added.error()); Added = addPass(Pipeline, TargetInfo.InstrInfo); diff --git a/backend/unittests/Target/RISCVLateCodeGenTest.cpp b/backend/unittests/Target/RISCVLateCodeGenTest.cpp index 955af50..8160370 100644 --- a/backend/unittests/Target/RISCVLateCodeGenTest.cpp +++ b/backend/unittests/Target/RISCVLateCodeGenTest.cpp @@ -10,7 +10,6 @@ #include "rcc/CodeGen/MachineBranchRelaxation.h" #include "rcc/CodeGen/MachineCFGUpdater.h" #include "rcc/CodeGen/MachineCopyPropagation.h" -#include "rcc/CodeGen/MachineFallthrough.h" #include "rcc/CodeGen/MachineFinalization.h" #include "rcc/CodeGen/MachineFunction.h" #include "rcc/CodeGen/MachineIRBuilder.h" @@ -384,77 +383,6 @@ void testBlockPlacement(TestContext &Context, const rcc::TargetDescription &Targ "block placement must put the highest-probability successor on the trace"); } -void testFallthroughNormalization(TestContext &Context, const rcc::TargetDescription &Target) { - auto Function = makeFunction(Context, "fallthrough", 2); - if (!Function) - return; - rcc::MachineBasicBlock *Entry = appendBlock(Context, *Function); - rcc::MachineBasicBlock *False = appendBlock(Context, *Function); - rcc::MachineBasicBlock *True = appendBlock(Context, *Function); - if (Entry == nullptr || False == nullptr || True == nullptr) - return; - auto Half = rcc::BranchProbability::fromFraction(1, 2); - auto CFG = Function->cfgUpdater(); - Context.expect(Half && CFG.addSuccessor(*Entry, *True, *Half).has_value() && - CFG.addSuccessor(*Entry, *False, *Half).has_value(), - "fallthrough CFG construction must succeed"); - rcc::MachineIRBuilder Builder(*Function, Target); - Context.expect(Builder.setInsertPoint(*Entry).has_value(), - "fallthrough insertion point must be established"); - rcc::MachineInstr *Conditional = - buildConditional(Context, Builder, rcc::riscv::InstructionOpcode::BEQ, *True); - rcc::MachineInstr *Jump = buildJAL(Context, Builder, *False); - if (Conditional == nullptr || Jump == nullptr) - return; - setPostRAProperties(*Function); - auto Liveness = rcc::rebuildMachineLiveness(*Function, Target); - Context.expect(Liveness.has_value(), "fallthrough fixture liveness must be rebuilt"); - rcc::MachineFunctionAnalysisManager Analyses; - rcc::MachineFallthroughPass Pass(rcc::riscv::instrInfo()); - auto Result = Pass.run(*Function, Target, Analyses); - if (!Result) - std::cerr << "fallthrough normalization failure: " << Result.error().message() << '\n'; - Context.expect(Result && Result->Changed && Conditional->next() == nullptr && - Jump->parent() == nullptr, - "fallthrough normalization must remove a jump to the next block"); -} - -void testFallthroughMaterialization(TestContext &Context, const rcc::TargetDescription &Target) { - auto Function = makeFunction(Context, "fallthrough_materialization", 8); - if (!Function) - return; - rcc::MachineBasicBlock *Entry = appendBlock(Context, *Function); - rcc::MachineBasicBlock *Padding = appendBlock(Context, *Function); - rcc::MachineBasicBlock *True = appendBlock(Context, *Function); - rcc::MachineBasicBlock *False = appendBlock(Context, *Function); - if (Entry == nullptr || Padding == nullptr || True == nullptr || False == nullptr) - return; - auto Half = rcc::BranchProbability::fromFraction(1, 2); - auto CFG = Function->cfgUpdater(); - Context.expect(Half && CFG.addSuccessor(*Entry, *True, *Half).has_value() && - CFG.addSuccessor(*Entry, *False, *Half).has_value(), - "materialized fallthrough CFG construction must succeed"); - rcc::MachineIRBuilder Builder(*Function, Target); - Context.expect(Builder.setInsertPoint(*Entry).has_value(), - "materialized fallthrough insertion point must be established"); - rcc::MachineInstr *Conditional = - buildConditional(Context, Builder, rcc::riscv::InstructionOpcode::BNE, *True); - if (Conditional == nullptr) - return; - setPostRAProperties(*Function); - Context.expect(rcc::rebuildMachineLiveness(*Function, Target).has_value(), - "materialized fallthrough liveness must be rebuilt"); - rcc::MachineFunctionAnalysisManager Analyses; - rcc::MachineFallthroughPass Pass(rcc::riscv::instrInfo()); - auto Result = Pass.run(*Function, Target, Analyses); - if (!Result) - std::cerr << "fallthrough materialization failure: " << Result.error().message() << '\n'; - Context.expect(Result && Result->Changed && Conditional->next() != nullptr && - Conditional->next()->opcode() == opcode(rcc::riscv::InstructionOpcode::JAL) && - branchTarget(*Conditional->next()) == False, - "fallthrough normalization must materialize a displaced false edge"); -} - void testBranchOptimization(TestContext &Context, const rcc::TargetDescription &Target) { auto Function = makeFunction(Context, "branch_optimization", 9); if (!Function) @@ -1359,8 +1287,6 @@ int main() { if (!Target) return Context.result(); testBlockPlacement(Context, *Target); - testFallthroughNormalization(Context, *Target); - testFallthroughMaterialization(Context, *Target); testBranchOptimization(Context, *Target); testTailDuplication(Context, *Target); testBranchFoldingTailMerge(Context, *Target); -- cgit v1.2.3