From 236082a0fe4dcd0362c5c74923a93e3db6a01291 Mon Sep 17 00:00:00 2001 From: Richard-Qin-X Date: Thu, 13 Aug 2026 05:45:37 +0800 Subject: [CodeGen] Align pass manager ownership --- backend/include/rcc/IR/PassInstrumentation.h | 227 +++++++++++++++++++++++++++ 1 file changed, 227 insertions(+) create mode 100644 backend/include/rcc/IR/PassInstrumentation.h (limited to 'backend/include/rcc/IR/PassInstrumentation.h') diff --git a/backend/include/rcc/IR/PassInstrumentation.h b/backend/include/rcc/IR/PassInstrumentation.h new file mode 100644 index 0000000..082ec81 --- /dev/null +++ b/backend/include/rcc/IR/PassInstrumentation.h @@ -0,0 +1,227 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef RCC_IR_PASSINSTRUMENTATION_H +#define RCC_IR_PASSINSTRUMENTATION_H + +#include "rcc/CodeGen/MachineFunctionAnalysisManager.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace rcc { + +class CompilationUnit; +class MachineFunction; +class TargetDescription; +struct MachinePassResult; +struct CompilationUnitPassResult; + +enum class InstrumentationPhase : std::uint8_t { + Before, + After, +}; + +struct InstrumentationStatistic final { + std::string Name; + bool IsAnalysis = false; + std::uint64_t Invocations = 0; + std::uint64_t CacheHits = 0; + std::uint64_t Changes = 0; + std::uint64_t Failures = 0; + std::uint64_t TotalNanoseconds = 0; +}; + +struct MachineActionID final { + std::string Pass; + std::string Rule; + MachineFunctionStableID Function; + MachineInstrStableID Instruction; + + [[nodiscard]] std::string toString() const; + + friend bool operator==(const MachineActionID &, const MachineActionID &) = default; +}; + +struct MachineActionEvent final { + MachineActionID ID; + std::uint64_t Cost = 0; + bool Accepted = false; + + friend bool operator==(const MachineActionEvent &, const MachineActionEvent &) = default; +}; + +class MachinePassInstrumentation final { +public: + using BeforeCallback = std::function; + using AfterCallback = + std::function; + using FailureCallback = + std::function; + using BeforeAnalysisCallback = std::function; + using AfterAnalysisCallback = + std::function; + using AnalysisFailureCallback = + std::function; + using IRPrintCallback = + std::function; + using ChangeCallback = + std::function; + using ActionFilter = std::function; + + using BeforeUnitCallback = std::function; + using AfterUnitCallback = std::function; + using UnitFailureCallback = + std::function; + using BeforeUnitAnalysisCallback = std::function; + using AfterUnitAnalysisCallback = + std::function; + using UnitAnalysisFailureCallback = + std::function; + + void addBeforeCallback(BeforeCallback Callback); + void addAfterCallback(AfterCallback Callback); + void addFailureCallback(FailureCallback Callback); + void addBeforeAnalysisCallback(BeforeAnalysisCallback Callback); + void addAfterAnalysisCallback(AfterAnalysisCallback Callback); + void addAnalysisFailureCallback(AnalysisFailureCallback Callback); + void addIRPrintCallback(IRPrintCallback Callback); + void addChangeCallback(ChangeCallback Callback); + void setActionFilter(ActionFilter Filter); + void setPerFunctionFuel(std::optional Fuel); + + void addBeforeUnitCallback(BeforeUnitCallback Callback); + void addAfterUnitCallback(AfterUnitCallback Callback); + void addUnitFailureCallback(UnitFailureCallback Callback); + void addBeforeUnitAnalysisCallback(BeforeUnitAnalysisCallback Callback); + void addAfterUnitAnalysisCallback(AfterUnitAnalysisCallback Callback); + void addUnitAnalysisFailureCallback(UnitAnalysisFailureCallback Callback); + + [[nodiscard]] std::vector statistics() const; + [[nodiscard]] std::vector actionEvents() const; + + [[nodiscard]] Expected requestAction(std::string_view Pass, std::string_view Rule, + const MachineFunction &Function, + MachineInstrStableID Instruction, std::uint64_t Cost); + [[nodiscard]] Expected requestAction(std::string_view Pass, std::string_view Rule, + const MachineFunction &Function, std::nullptr_t, + std::uint64_t Cost); + +private: + struct BufferedEvents final { + const TargetDescription *Target = nullptr; + std::vector> Events; + }; + + [[nodiscard]] bool bufferFunctionEvent(const MachineFunction &Function, + std::function Replay) const; + void beginBuffering(BufferedEvents &Buffer, const TargetDescription &Target) const noexcept; + void endBuffering() const noexcept; + void replayBufferedEvents(BufferedEvents &Buffer) const; + + void before(std::string_view Name, const MachineFunction &Function) const; + void after(std::string_view Name, const MachineFunction &Function, + const MachinePassResult &Result, std::uint64_t Nanoseconds) const; + void failure(std::string_view Name, const MachineFunction &Function, const Error &ErrorValue, + std::uint64_t Nanoseconds = 0) const; + void beforeAnalysis(std::string_view Name, const MachineFunction &Function) const; + void afterAnalysis(std::string_view Name, const MachineFunction &Function, bool CacheHit, + std::uint64_t Nanoseconds) const; + void analysisFailure(std::string_view Name, const MachineFunction &Function, + const Error &ErrorValue, std::uint64_t Nanoseconds) const; + void change(std::string_view Name, const MachineFunction &Function, MachinePassChanges Changes, + bool FingerprintChanged) const; + + void beforeUnit(std::string_view Name, const CompilationUnit &Unit) const; + void afterUnit(std::string_view Name, const CompilationUnit &Unit, + const CompilationUnitPassResult &Result, std::uint64_t Nanoseconds) const; + void unitFailure(std::string_view Name, const CompilationUnit &Unit, const Error &ErrorValue, + std::uint64_t Nanoseconds = 0) const; + void beforeAnalysis(std::string_view Name, const CompilationUnit &Unit) const; + void afterAnalysis(std::string_view Name, const CompilationUnit &Unit, bool CacheHit, + std::uint64_t Nanoseconds) const; + void analysisFailure(std::string_view Name, const CompilationUnit &Unit, const Error &ErrorValue, + std::uint64_t Nanoseconds) const; + + [[nodiscard]] InstrumentationStatistic &statistic(std::string_view Name, bool IsAnalysis) const; + + mutable std::mutex Mutex; + mutable std::mutex ActionMutex; + std::vector Before; + std::vector After; + std::vector Failure; + std::vector BeforeAnalysis; + std::vector AfterAnalysis; + std::vector AnalysisFailure; + std::vector IRPrint; + std::vector Change; + ActionFilter Filter; + std::optional PerFunctionFuel; + std::unordered_map ConsumedFuel; + std::vector ActionEvents; + + std::vector BeforeUnit; + std::vector AfterUnit; + std::vector UnitFailure; + std::vector BeforeUnitAnalysis; + std::vector AfterUnitAnalysis; + std::vector UnitAnalysisFailure; + mutable std::unordered_map Statistics; + + static thread_local BufferedEvents *ActiveBuffer; + + template friend struct AnalysisManagerInstrumentation; + template friend struct PassManagerCallbacks; +}; + +class MachineActionReplay final { +public: + template + explicit MachineActionReplay(AnalysisManagerT &Analyses) + : Request([&Analyses](std::string_view Rule, const MachineFunction &Function, + MachineInstrStableID Instruction, std::uint64_t Cost) { + return Analyses.requestAction(Rule, Function, Instruction, Cost); + }) {} + + template + MachineActionReplay( + AnalysisManagerT &Analyses, + const std::unordered_map &SourceToClone) + : MachineActionReplay(Analyses) { + for (const auto &[Source, Clone] : SourceToClone) + RecordingInstructionIDs.try_emplace(Clone, Source); + } + + [[nodiscard]] Expected request(std::string_view Rule, const MachineFunction &Function, + MachineInstrStableID Instruction = {}, + std::uint64_t Cost = 1); + void beginReplay() noexcept; + [[nodiscard]] Expected finishReplay() const; + +private: + struct Decision final { + std::string Rule; + MachineFunctionStableID Function; + MachineInstrStableID Instruction; + std::uint64_t Cost = 0; + bool Accepted = false; + }; + + std::function(std::string_view, const MachineFunction &, MachineInstrStableID, + std::uint64_t)> + Request; + std::unordered_map RecordingInstructionIDs; + std::vector Decisions; + std::size_t NextDecision = 0; + bool IsReplaying = false; +}; + +} // namespace rcc + +#endif // RCC_IR_PASSINSTRUMENTATION_H -- cgit v1.2.3