diff options
| author | Richard-Qin-X <richard.qin.001@gmail.com> | 2026-08-28 13:58:47 +0800 |
|---|---|---|
| committer | Richard-Qin-X <richard.qin.001@gmail.com> | 2026-08-28 13:58:47 +0800 |
| commit | 8c878ada4e1df8b37aea9ff44a5fb2b25d2b2a1f (patch) | |
| tree | c2c3ac9221550719b7f873de333ec6803f284a7e | |
| parent | 4813e41cb6765e1b87acf12c485f75c04c1938ff (diff) | |
| download | rcc-project-8c878ada4e1df8b37aea9ff44a5fb2b25d2b2a1f.tar.gz rcc-project-8c878ada4e1df8b37aea9ff44a5fb2b25d2b2a1f.tar.xz | |
[CodeGen] Separate pass instrumentation ownership
| -rw-r--r-- | backend/include/rcc/CodeGen/MachinePassInstrumentation.h | 153 | ||||
| -rw-r--r-- | backend/include/rcc/CodeGen/MachinePassManager.h | 2 | ||||
| -rw-r--r-- | backend/include/rcc/IR/PassInstrumentation.h | 219 | ||||
| -rw-r--r-- | backend/lib/CodeGen/CMakeLists.txt | 3 | ||||
| -rw-r--r-- | backend/lib/CodeGen/MachinePassInstrumentation.cpp | 407 | ||||
| -rw-r--r-- | backend/lib/CodeGen/MachinePassManager.cpp | 475 | ||||
| -rw-r--r-- | backend/lib/IR/CMakeLists.txt | 1 |
7 files changed, 648 insertions, 612 deletions
diff --git a/backend/include/rcc/CodeGen/MachinePassInstrumentation.h b/backend/include/rcc/CodeGen/MachinePassInstrumentation.h new file mode 100644 index 0000000..9cc5098 --- /dev/null +++ b/backend/include/rcc/CodeGen/MachinePassInstrumentation.h @@ -0,0 +1,153 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef RCC_CODEGEN_MACHINEPASSINSTRUMENTATION_H +#define RCC_CODEGEN_MACHINEPASSINSTRUMENTATION_H + +#include "rcc/CodeGen/MachineFunctionAnalysisManager.h" +#include "rcc/IR/PassInstrumentation.h" + +#include <cstdint> +#include <functional> +#include <mutex> +#include <optional> +#include <string> +#include <string_view> +#include <unordered_map> +#include <vector> + +namespace rcc { + +class CompilationUnit; +class MachineFunction; +struct MachinePassResult; +struct CompilationUnitPassResult; + +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 { + using FunctionCallbackRegistry = PassInstrumentationCallbacks<MachineFunction, MachinePassResult>; + using UnitCallbackRegistry = + PassInstrumentationCallbacks<CompilationUnit, CompilationUnitPassResult>; + +public: + using BeforeCallback = FunctionCallbackRegistry::BeforeCallback; + using AfterCallback = FunctionCallbackRegistry::AfterCallback; + using FailureCallback = FunctionCallbackRegistry::FailureCallback; + using BeforeAnalysisCallback = FunctionCallbackRegistry::BeforeAnalysisCallback; + using AfterAnalysisCallback = FunctionCallbackRegistry::AfterAnalysisCallback; + using AnalysisFailureCallback = FunctionCallbackRegistry::AnalysisFailureCallback; + using IRPrintCallback = + std::function<void(InstrumentationPhase, std::string_view, const MachineFunction &)>; + using ChangeCallback = + std::function<void(std::string_view, const MachineFunction &, MachinePassChanges, bool)>; + using ActionFilter = std::function<bool(const MachineActionID &, std::uint64_t)>; + + using BeforeUnitCallback = UnitCallbackRegistry::BeforeCallback; + using AfterUnitCallback = UnitCallbackRegistry::AfterCallback; + using UnitFailureCallback = UnitCallbackRegistry::FailureCallback; + using BeforeUnitAnalysisCallback = UnitCallbackRegistry::BeforeAnalysisCallback; + using AfterUnitAnalysisCallback = UnitCallbackRegistry::AfterAnalysisCallback; + using UnitAnalysisFailureCallback = UnitCallbackRegistry::AnalysisFailureCallback; + + 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<std::uint64_t> 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<InstrumentationStatistic> statistics() const; + [[nodiscard]] std::vector<MachineActionEvent> actionEvents() const; + [[nodiscard]] bool requiresSerialFunctionExecution() const; + + [[nodiscard]] Expected<bool> requestAction(std::string_view Pass, std::string_view Rule, + const MachineFunction &Function, + MachineInstrStableID Instruction, std::uint64_t Cost); + [[nodiscard]] Expected<bool> requestAction(std::string_view Pass, std::string_view Rule, + const MachineFunction &Function, std::nullptr_t, + std::uint64_t Cost); + +private: + 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; + + FunctionCallbackRegistry FunctionCallbacks; + UnitCallbackRegistry UnitCallbacks; + mutable std::mutex Mutex; + mutable std::mutex ActionMutex; + std::vector<IRPrintCallback> IRPrint; + std::vector<ChangeCallback> Change; + ActionFilter Filter; + std::optional<std::uint64_t> PerFunctionFuel; + std::unordered_map<std::uint64_t, std::uint64_t> ConsumedFuel; + std::vector<MachineActionEvent> ActionEvents; + mutable std::unordered_map<std::string, InstrumentationStatistic> Statistics; + + template <typename, typename> friend struct AnalysisManagerInstrumentation; + template <typename, typename, typename> friend struct PassManagerCallbacks; +}; + +} // namespace rcc + +#endif // RCC_CODEGEN_MACHINEPASSINSTRUMENTATION_H diff --git a/backend/include/rcc/CodeGen/MachinePassManager.h b/backend/include/rcc/CodeGen/MachinePassManager.h index 3587395..af7a5d3 100644 --- a/backend/include/rcc/CodeGen/MachinePassManager.h +++ b/backend/include/rcc/CodeGen/MachinePassManager.h @@ -6,7 +6,7 @@ #include "rcc/CodeGen/InstructionDescriptor.h" #include "rcc/CodeGen/MachineFunctionAnalysisManager.h" #include "rcc/CodeGen/MachineFunctionProperties.h" -#include "rcc/IR/PassInstrumentation.h" +#include "rcc/CodeGen/MachinePassInstrumentation.h" #include <cstddef> #include <memory> diff --git a/backend/include/rcc/IR/PassInstrumentation.h b/backend/include/rcc/IR/PassInstrumentation.h index 8ba2d2e..b0a673a 100644 --- a/backend/include/rcc/IR/PassInstrumentation.h +++ b/backend/include/rcc/IR/PassInstrumentation.h @@ -3,168 +3,117 @@ #ifndef RCC_IR_PASSINSTRUMENTATION_H #define RCC_IR_PASSINSTRUMENTATION_H -#include "rcc/CodeGen/MachineFunctionAnalysisManager.h" +#include "rcc/Support/Error.h" #include <cstdint> #include <functional> #include <mutex> -#include <optional> -#include <string> #include <string_view> -#include <unordered_map> +#include <utility> #include <vector> namespace rcc { -class CompilationUnit; -class MachineFunction; -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 { +template <typename IRUnitT, typename PassResultT> class PassInstrumentationCallbacks final { public: - using BeforeCallback = std::function<void(std::string_view, const MachineFunction &)>; - using AfterCallback = - std::function<void(std::string_view, const MachineFunction &, const MachinePassResult &)>; - using FailureCallback = - std::function<void(std::string_view, const MachineFunction &, const Error &)>; - using BeforeAnalysisCallback = std::function<void(std::string_view, const MachineFunction &)>; + using BeforeCallback = std::function<void(std::string_view, const IRUnitT &)>; + using AfterCallback = std::function<void(std::string_view, const IRUnitT &, const PassResultT &)>; + using FailureCallback = std::function<void(std::string_view, const IRUnitT &, const Error &)>; + using BeforeAnalysisCallback = std::function<void(std::string_view, const IRUnitT &)>; using AfterAnalysisCallback = - std::function<void(std::string_view, const MachineFunction &, bool, std::uint64_t)>; + std::function<void(std::string_view, const IRUnitT &, bool, std::uint64_t)>; using AnalysisFailureCallback = - std::function<void(std::string_view, const MachineFunction &, const Error &)>; - using IRPrintCallback = - std::function<void(InstrumentationPhase, std::string_view, const MachineFunction &)>; - using ChangeCallback = - std::function<void(std::string_view, const MachineFunction &, MachinePassChanges, bool)>; - using ActionFilter = std::function<bool(const MachineActionID &, std::uint64_t)>; - - using BeforeUnitCallback = std::function<void(std::string_view, const CompilationUnit &)>; - using AfterUnitCallback = std::function<void(std::string_view, const CompilationUnit &, - const CompilationUnitPassResult &)>; - using UnitFailureCallback = - std::function<void(std::string_view, const CompilationUnit &, const Error &)>; - using BeforeUnitAnalysisCallback = std::function<void(std::string_view, const CompilationUnit &)>; - using AfterUnitAnalysisCallback = - std::function<void(std::string_view, const CompilationUnit &, bool, std::uint64_t)>; - using UnitAnalysisFailureCallback = - std::function<void(std::string_view, const CompilationUnit &, const Error &)>; - - 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<std::uint64_t> 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<InstrumentationStatistic> statistics() const; - [[nodiscard]] std::vector<MachineActionEvent> actionEvents() const; - [[nodiscard]] bool requiresSerialFunctionExecution() const; - - [[nodiscard]] Expected<bool> requestAction(std::string_view Pass, std::string_view Rule, - const MachineFunction &Function, - MachineInstrStableID Instruction, std::uint64_t Cost); - [[nodiscard]] Expected<bool> requestAction(std::string_view Pass, std::string_view Rule, - const MachineFunction &Function, std::nullptr_t, - std::uint64_t Cost); + std::function<void(std::string_view, const IRUnitT &, const Error &)>; + + void addBeforeCallback(BeforeCallback Callback) { + addCallback(Before, std::move(Callback)); + } + + void addAfterCallback(AfterCallback Callback) { + addCallback(After, std::move(Callback)); + } + + void addFailureCallback(FailureCallback Callback) { + addCallback(Failure, std::move(Callback)); + } + + void addBeforeAnalysisCallback(BeforeAnalysisCallback Callback) { + addCallback(BeforeAnalysis, std::move(Callback)); + } + + void addAfterAnalysisCallback(AfterAnalysisCallback Callback) { + addCallback(AfterAnalysis, std::move(Callback)); + } + + void addAnalysisFailureCallback(AnalysisFailureCallback Callback) { + addCallback(AnalysisFailure, std::move(Callback)); + } + + void runBefore(std::string_view Name, const IRUnitT &Unit) const { + for (const BeforeCallback &Callback : snapshot(Before)) + Callback(Name, Unit); + } + + void runAfter(std::string_view Name, const IRUnitT &Unit, const PassResultT &Result) const { + for (const AfterCallback &Callback : snapshot(After)) + Callback(Name, Unit, Result); + } + + void runFailure(std::string_view Name, const IRUnitT &Unit, const Error &FailureValue) const { + for (const FailureCallback &Callback : snapshot(Failure)) + Callback(Name, Unit, FailureValue); + } + + void runBeforeAnalysis(std::string_view Name, const IRUnitT &Unit) const { + for (const BeforeAnalysisCallback &Callback : snapshot(BeforeAnalysis)) + Callback(Name, Unit); + } + + void runAfterAnalysis(std::string_view Name, const IRUnitT &Unit, bool CacheHit, + std::uint64_t Nanoseconds) const { + for (const AfterAnalysisCallback &Callback : snapshot(AfterAnalysis)) + Callback(Name, Unit, CacheHit, Nanoseconds); + } + + void runAnalysisFailure(std::string_view Name, const IRUnitT &Unit, + const Error &FailureValue) const { + for (const AnalysisFailureCallback &Callback : snapshot(AnalysisFailure)) + Callback(Name, Unit, FailureValue); + } + + [[nodiscard]] bool empty() const { + std::scoped_lock Lock(Mutex); + return Before.empty() && After.empty() && Failure.empty() && BeforeAnalysis.empty() && + AfterAnalysis.empty() && AnalysisFailure.empty(); + } private: - 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; + template <typename CallbackT> + void addCallback(std::vector<CallbackT> &Callbacks, CallbackT Callback) { + if (!Callback) + return; + std::scoped_lock Lock(Mutex); + Callbacks.push_back(std::move(Callback)); + } + + template <typename CallbackT> + [[nodiscard]] std::vector<CallbackT> snapshot(const std::vector<CallbackT> &Callbacks) const { + std::scoped_lock Lock(Mutex); + return Callbacks; + } mutable std::mutex Mutex; - mutable std::mutex ActionMutex; std::vector<BeforeCallback> Before; std::vector<AfterCallback> After; std::vector<FailureCallback> Failure; std::vector<BeforeAnalysisCallback> BeforeAnalysis; std::vector<AfterAnalysisCallback> AfterAnalysis; std::vector<AnalysisFailureCallback> AnalysisFailure; - std::vector<IRPrintCallback> IRPrint; - std::vector<ChangeCallback> Change; - ActionFilter Filter; - std::optional<std::uint64_t> PerFunctionFuel; - std::unordered_map<std::uint64_t, std::uint64_t> ConsumedFuel; - std::vector<MachineActionEvent> ActionEvents; - - std::vector<BeforeUnitCallback> BeforeUnit; - std::vector<AfterUnitCallback> AfterUnit; - std::vector<UnitFailureCallback> UnitFailure; - std::vector<BeforeUnitAnalysisCallback> BeforeUnitAnalysis; - std::vector<AfterUnitAnalysisCallback> AfterUnitAnalysis; - std::vector<UnitAnalysisFailureCallback> UnitAnalysisFailure; - mutable std::unordered_map<std::string, InstrumentationStatistic> Statistics; - - template <typename, typename> friend struct AnalysisManagerInstrumentation; - template <typename, typename, typename> friend struct PassManagerCallbacks; }; } // namespace rcc diff --git a/backend/lib/CodeGen/CMakeLists.txt b/backend/lib/CodeGen/CMakeLists.txt index a7a0586..8185d34 100644 --- a/backend/lib/CodeGen/CMakeLists.txt +++ b/backend/lib/CodeGen/CMakeLists.txt @@ -51,6 +51,7 @@ set( MachineOperand.cpp MachineOptimizationPipeline.cpp MachineOutliner.cpp + MachinePassInstrumentation.cpp MachinePassManager.cpp MachinePseudoExpansion.cpp MachineRegisterInfo.cpp @@ -147,8 +148,8 @@ set( "${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/MachineOptimizationPipeline.h" "${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/MachineOutliner.h" "${RCC_BACKEND_SOURCE_DIR}/include/rcc/IR/PassManager.h" - "${RCC_BACKEND_SOURCE_DIR}/include/rcc/IR/PassInstrumentation.h" "${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/MachineFunctionAnalysisManager.h" + "${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/MachinePassInstrumentation.h" "${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/MachinePassManager.h" "${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/MachinePseudoExpansion.h" "${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/PrologueEpilogueInsertion.h" diff --git a/backend/lib/CodeGen/MachinePassInstrumentation.cpp b/backend/lib/CodeGen/MachinePassInstrumentation.cpp new file mode 100644 index 0000000..ce8c62c --- /dev/null +++ b/backend/lib/CodeGen/MachinePassInstrumentation.cpp @@ -0,0 +1,407 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "rcc/CodeGen/MachinePassInstrumentation.h" + +#include "rcc/CodeGen/CompilationUnit.h" +#include "rcc/CodeGen/MachineFunction.h" +#include "rcc/CodeGen/MachinePassManager.h" + +#include <algorithm> +#include <ranges> +#include <utility> + +namespace rcc { + +void AnalysisManagerInstrumentation<MachineFunction, MachinePassInstrumentation>::beforeAnalysis( + MachinePassInstrumentation *Instrumentation, std::string_view Name, + const MachineFunction &Function) { + Instrumentation->beforeAnalysis(Name, Function); +} + +void AnalysisManagerInstrumentation<MachineFunction, MachinePassInstrumentation>::afterAnalysis( + MachinePassInstrumentation *Instrumentation, std::string_view Name, + const MachineFunction &Function, bool CacheHit, std::uint64_t Nanoseconds) { + Instrumentation->afterAnalysis(Name, Function, CacheHit, Nanoseconds); +} + +void AnalysisManagerInstrumentation<MachineFunction, MachinePassInstrumentation>::analysisFailure( + MachinePassInstrumentation *Instrumentation, std::string_view Name, + const MachineFunction &Function, const Error &Failure, std::uint64_t Nanoseconds) { + Instrumentation->analysisFailure(Name, Function, Failure, Nanoseconds); +} + +Expected<bool> +AnalysisManagerInstrumentation<MachineFunction, MachinePassInstrumentation>::requestAction( + MachinePassInstrumentation *Instrumentation, std::string_view Pass, std::string_view Rule, + const MachineFunction &Function, MachineInstrStableID Instruction, std::uint64_t Cost) { + return Instrumentation->requestAction(Pass, Rule, Function, Instruction, Cost); +} + +Expected<bool> +AnalysisManagerInstrumentation<MachineFunction, MachinePassInstrumentation>::requestAction( + MachinePassInstrumentation *Instrumentation, std::string_view Pass, std::string_view Rule, + const MachineFunction &Function, std::nullptr_t, std::uint64_t Cost) { + return Instrumentation->requestAction(Pass, Rule, Function, nullptr, Cost); +} + +void AnalysisManagerInstrumentation<CompilationUnit, MachinePassInstrumentation>::beforeAnalysis( + MachinePassInstrumentation *Instrumentation, std::string_view Name, + const CompilationUnit &Unit) { + Instrumentation->beforeAnalysis(Name, Unit); +} + +void AnalysisManagerInstrumentation<CompilationUnit, MachinePassInstrumentation>::afterAnalysis( + MachinePassInstrumentation *Instrumentation, std::string_view Name, const CompilationUnit &Unit, + bool CacheHit, std::uint64_t Nanoseconds) { + Instrumentation->afterAnalysis(Name, Unit, CacheHit, Nanoseconds); +} + +void AnalysisManagerInstrumentation<CompilationUnit, MachinePassInstrumentation>::analysisFailure( + MachinePassInstrumentation *Instrumentation, std::string_view Name, const CompilationUnit &Unit, + const Error &Failure, std::uint64_t Nanoseconds) { + Instrumentation->analysisFailure(Name, Unit, Failure, Nanoseconds); +} + +std::string MachineActionID::toString() const { + std::string Result; + Result.reserve(Pass.size() + Rule.size() + 48U); + Result.append(Pass); + Result.push_back(':'); + Result.append(Rule); + Result.append(":f"); + Result.append(std::to_string(Function.value())); + Result.append(":i"); + Result.append(std::to_string(Instruction.value())); + return Result; +} + +void MachinePassInstrumentation::addBeforeCallback(BeforeCallback Callback) { + FunctionCallbacks.addBeforeCallback(std::move(Callback)); +} + +void MachinePassInstrumentation::addAfterCallback(AfterCallback Callback) { + FunctionCallbacks.addAfterCallback(std::move(Callback)); +} + +void MachinePassInstrumentation::addFailureCallback(FailureCallback Callback) { + FunctionCallbacks.addFailureCallback(std::move(Callback)); +} + +void MachinePassInstrumentation::addBeforeAnalysisCallback(BeforeAnalysisCallback Callback) { + FunctionCallbacks.addBeforeAnalysisCallback(std::move(Callback)); +} + +void MachinePassInstrumentation::addAfterAnalysisCallback(AfterAnalysisCallback Callback) { + FunctionCallbacks.addAfterAnalysisCallback(std::move(Callback)); +} + +void MachinePassInstrumentation::addAnalysisFailureCallback(AnalysisFailureCallback Callback) { + FunctionCallbacks.addAnalysisFailureCallback(std::move(Callback)); +} + +void MachinePassInstrumentation::addIRPrintCallback(IRPrintCallback Callback) { + if (!Callback) + return; + std::scoped_lock Lock(Mutex); + IRPrint.push_back(std::move(Callback)); +} + +void MachinePassInstrumentation::addChangeCallback(ChangeCallback Callback) { + if (!Callback) + return; + std::scoped_lock Lock(Mutex); + Change.push_back(std::move(Callback)); +} + +void MachinePassInstrumentation::setActionFilter(ActionFilter NewFilter) { + std::scoped_lock Lock(Mutex); + Filter = std::move(NewFilter); +} + +void MachinePassInstrumentation::setPerFunctionFuel(std::optional<std::uint64_t> Fuel) { + std::scoped_lock Lock(Mutex); + PerFunctionFuel = Fuel; + ConsumedFuel.clear(); + ActionEvents.clear(); +} + +void MachinePassInstrumentation::addBeforeUnitCallback(BeforeUnitCallback Callback) { + UnitCallbacks.addBeforeCallback(std::move(Callback)); +} + +void MachinePassInstrumentation::addAfterUnitCallback(AfterUnitCallback Callback) { + UnitCallbacks.addAfterCallback(std::move(Callback)); +} + +void MachinePassInstrumentation::addUnitFailureCallback(UnitFailureCallback Callback) { + UnitCallbacks.addFailureCallback(std::move(Callback)); +} + +void MachinePassInstrumentation::addBeforeUnitAnalysisCallback( + BeforeUnitAnalysisCallback Callback) { + UnitCallbacks.addBeforeAnalysisCallback(std::move(Callback)); +} + +void MachinePassInstrumentation::addAfterUnitAnalysisCallback(AfterUnitAnalysisCallback Callback) { + UnitCallbacks.addAfterAnalysisCallback(std::move(Callback)); +} + +void MachinePassInstrumentation::addUnitAnalysisFailureCallback( + UnitAnalysisFailureCallback Callback) { + UnitCallbacks.addAnalysisFailureCallback(std::move(Callback)); +} + +InstrumentationStatistic &MachinePassInstrumentation::statistic(std::string_view Name, + bool IsAnalysis) const { + const std::string Key = std::string(IsAnalysis ? "analysis:" : "pass:") + std::string(Name); + auto [Position, Inserted] = Statistics.try_emplace(Key); + if (Inserted) { + Position->second.Name = std::string(Name); + Position->second.IsAnalysis = IsAnalysis; + } + return Position->second; +} + +void MachinePassInstrumentation::before(std::string_view Name, + const MachineFunction &Function) const { + FunctionCallbacks.runBefore(Name, Function); + std::vector<IRPrintCallback> Printers; + { + std::scoped_lock Lock(Mutex); + Printers = IRPrint; + } + for (const IRPrintCallback &Printer : Printers) + Printer(InstrumentationPhase::Before, Name, Function); +} + +void MachinePassInstrumentation::after(std::string_view Name, const MachineFunction &Function, + const MachinePassResult &Result, + std::uint64_t Nanoseconds) const { + std::vector<IRPrintCallback> Printers; + { + std::scoped_lock Lock(Mutex); + InstrumentationStatistic &Record = statistic(Name, false); + ++Record.Invocations; + Record.Changes += Result.Changed ? 1U : 0U; + Record.TotalNanoseconds += Nanoseconds; + Printers = IRPrint; + } + FunctionCallbacks.runAfter(Name, Function, Result); + for (const IRPrintCallback &Printer : Printers) + Printer(InstrumentationPhase::After, Name, Function); +} + +void MachinePassInstrumentation::failure(std::string_view Name, const MachineFunction &Function, + const Error &ErrorValue, std::uint64_t Nanoseconds) const { + { + std::scoped_lock Lock(Mutex); + InstrumentationStatistic &Record = statistic(Name, false); + ++Record.Invocations; + ++Record.Failures; + Record.TotalNanoseconds += Nanoseconds; + } + FunctionCallbacks.runFailure(Name, Function, ErrorValue); +} + +void MachinePassInstrumentation::beforeAnalysis(std::string_view Name, + const MachineFunction &Function) const { + FunctionCallbacks.runBeforeAnalysis(Name, Function); +} + +void MachinePassInstrumentation::afterAnalysis(std::string_view Name, + const MachineFunction &Function, bool CacheHit, + std::uint64_t Nanoseconds) const { + { + std::scoped_lock Lock(Mutex); + InstrumentationStatistic &Record = statistic(Name, true); + ++Record.Invocations; + Record.CacheHits += CacheHit ? 1U : 0U; + Record.TotalNanoseconds += Nanoseconds; + } + FunctionCallbacks.runAfterAnalysis(Name, Function, CacheHit, Nanoseconds); +} + +void MachinePassInstrumentation::analysisFailure(std::string_view Name, + const MachineFunction &Function, + const Error &ErrorValue, + std::uint64_t Nanoseconds) const { + { + std::scoped_lock Lock(Mutex); + InstrumentationStatistic &Record = statistic(Name, true); + ++Record.Invocations; + ++Record.Failures; + Record.TotalNanoseconds += Nanoseconds; + } + FunctionCallbacks.runAnalysisFailure(Name, Function, ErrorValue); +} + +void MachinePassInstrumentation::change(std::string_view Name, const MachineFunction &Function, + MachinePassChanges Changes, bool FingerprintChanged) const { + std::vector<ChangeCallback> Callbacks; + { + std::scoped_lock Lock(Mutex); + Callbacks = Change; + } + for (const ChangeCallback &Callback : Callbacks) + Callback(Name, Function, Changes, FingerprintChanged); +} + +Expected<bool> MachinePassInstrumentation::requestAction(std::string_view Pass, + std::string_view Rule, + const MachineFunction &Function, + MachineInstrStableID Instruction, + std::uint64_t Cost) { + MachineActionID Action{ + .Pass = std::string(Pass), + .Rule = std::string(Rule), + .Function = Function.stableID(), + .Instruction = Instruction, + }; + if (Action.Pass.empty() || Action.Rule.empty() || Action.Function != Function.stableID() || + Cost == 0) { + return makeUnexpected(ErrorCode::InvalidArgument, "machine action identity is invalid"); + } + std::scoped_lock ActionLock(ActionMutex); + ActionFilter CurrentFilter; + { + std::scoped_lock Lock(Mutex); + CurrentFilter = Filter; + } + if (CurrentFilter && !CurrentFilter(Action, Cost)) { + std::scoped_lock Lock(Mutex); + ActionEvents.push_back({Action, Cost, false}); + return false; + } + + std::scoped_lock Lock(Mutex); + if (!PerFunctionFuel) { + ActionEvents.push_back({Action, Cost, true}); + return true; + } + std::uint64_t &Consumed = ConsumedFuel[Function.stableID().value()]; + if (Consumed > *PerFunctionFuel || Cost > *PerFunctionFuel - Consumed) { + ActionEvents.push_back({Action, Cost, false}); + return false; + } + Consumed += Cost; + ActionEvents.push_back({Action, Cost, true}); + return true; +} + +Expected<bool> MachinePassInstrumentation::requestAction(std::string_view Pass, + std::string_view Rule, + const MachineFunction &Function, + std::nullptr_t, std::uint64_t Cost) { + return requestAction(Pass, Rule, Function, MachineInstrStableID{}, Cost); +} + +void MachinePassInstrumentation::beforeUnit(std::string_view Name, + const CompilationUnit &Unit) const { + UnitCallbacks.runBefore(Name, Unit); +} + +void MachinePassInstrumentation::afterUnit(std::string_view Name, const CompilationUnit &Unit, + const CompilationUnitPassResult &Result, + std::uint64_t Nanoseconds) const { + { + std::scoped_lock Lock(Mutex); + InstrumentationStatistic &Record = statistic("unit:" + std::string(Name), false); + ++Record.Invocations; + Record.Changes += Result.Changed ? 1U : 0U; + Record.TotalNanoseconds += Nanoseconds; + } + UnitCallbacks.runAfter(Name, Unit, Result); +} + +void MachinePassInstrumentation::unitFailure(std::string_view Name, const CompilationUnit &Unit, + const Error &ErrorValue, + std::uint64_t Nanoseconds) const { + { + std::scoped_lock Lock(Mutex); + InstrumentationStatistic &Record = statistic("unit:" + std::string(Name), false); + ++Record.Invocations; + ++Record.Failures; + Record.TotalNanoseconds += Nanoseconds; + } + UnitCallbacks.runFailure(Name, Unit, ErrorValue); +} + +void MachinePassInstrumentation::beforeAnalysis(std::string_view Name, + const CompilationUnit &Unit) const { + UnitCallbacks.runBeforeAnalysis(Name, Unit); +} + +void MachinePassInstrumentation::afterAnalysis(std::string_view Name, const CompilationUnit &Unit, + bool CacheHit, std::uint64_t Nanoseconds) const { + { + std::scoped_lock Lock(Mutex); + InstrumentationStatistic &Record = statistic("unit:" + std::string(Name), true); + ++Record.Invocations; + Record.CacheHits += CacheHit ? 1U : 0U; + Record.TotalNanoseconds += Nanoseconds; + } + UnitCallbacks.runAfterAnalysis(Name, Unit, CacheHit, Nanoseconds); +} + +void MachinePassInstrumentation::analysisFailure(std::string_view Name, const CompilationUnit &Unit, + const Error &ErrorValue, + std::uint64_t Nanoseconds) const { + { + std::scoped_lock Lock(Mutex); + InstrumentationStatistic &Record = statistic("unit:" + std::string(Name), true); + ++Record.Invocations; + ++Record.Failures; + Record.TotalNanoseconds += Nanoseconds; + } + UnitCallbacks.runAnalysisFailure(Name, Unit, ErrorValue); +} + +std::vector<InstrumentationStatistic> MachinePassInstrumentation::statistics() const { + std::vector<InstrumentationStatistic> Result; + { + std::scoped_lock Lock(Mutex); + Result.reserve(Statistics.size()); + for (const auto &[Key, Record] : Statistics) { + (void)Key; + Result.push_back(Record); + } + } + std::ranges::sort( + Result, [](const InstrumentationStatistic &Left, const InstrumentationStatistic &Right) { + if (Left.IsAnalysis != Right.IsAnalysis) + return Left.IsAnalysis < Right.IsAnalysis; + return Left.Name < Right.Name; + }); + return Result; +} + +std::vector<MachineActionEvent> MachinePassInstrumentation::actionEvents() const { + std::vector<MachineActionEvent> Result; + { + std::scoped_lock Lock(Mutex); + Result = ActionEvents; + } + std::ranges::sort(Result, [](const MachineActionEvent &Left, const MachineActionEvent &Right) { + if (Left.ID.Function.value() != Right.ID.Function.value()) + return Left.ID.Function.value() < Right.ID.Function.value(); + if (Left.ID.Instruction.value() != Right.ID.Instruction.value()) + return Left.ID.Instruction.value() < Right.ID.Instruction.value(); + if (Left.ID.Pass != Right.ID.Pass) + return Left.ID.Pass < Right.ID.Pass; + if (Left.ID.Rule != Right.ID.Rule) + return Left.ID.Rule < Right.ID.Rule; + if (Left.Cost != Right.Cost) + return Left.Cost < Right.Cost; + return Left.Accepted < Right.Accepted; + }); + return Result; +} + +bool MachinePassInstrumentation::requiresSerialFunctionExecution() const { + if (!FunctionCallbacks.empty()) + return true; + std::scoped_lock Lock(Mutex); + return !IRPrint.empty() || !Change.empty(); +} + +} // namespace rcc diff --git a/backend/lib/CodeGen/MachinePassManager.cpp b/backend/lib/CodeGen/MachinePassManager.cpp index fc3f6be..3d56357 100644 --- a/backend/lib/CodeGen/MachinePassManager.cpp +++ b/backend/lib/CodeGen/MachinePassManager.cpp @@ -15,11 +15,8 @@ #include <chrono> #include <cstddef> #include <cstdint> -#include <limits> #include <memory> #include <optional> -#include <ranges> -#include <set> #include <string> #include <string_view> #include <thread> @@ -132,478 +129,6 @@ void combineFingerprint(std::uint64_t &State, std::uint64_t Value) noexcept { } // namespace -void AnalysisManagerInstrumentation<MachineFunction, MachinePassInstrumentation>::beforeAnalysis( - MachinePassInstrumentation *Instrumentation, std::string_view Name, - const MachineFunction &Function) { - Instrumentation->beforeAnalysis(Name, Function); -} - -void AnalysisManagerInstrumentation<MachineFunction, MachinePassInstrumentation>::afterAnalysis( - MachinePassInstrumentation *Instrumentation, std::string_view Name, - const MachineFunction &Function, bool CacheHit, std::uint64_t Nanoseconds) { - Instrumentation->afterAnalysis(Name, Function, CacheHit, Nanoseconds); -} - -void AnalysisManagerInstrumentation<MachineFunction, MachinePassInstrumentation>::analysisFailure( - MachinePassInstrumentation *Instrumentation, std::string_view Name, - const MachineFunction &Function, const Error &Failure, std::uint64_t Nanoseconds) { - Instrumentation->analysisFailure(Name, Function, Failure, Nanoseconds); -} - -Expected<bool> -AnalysisManagerInstrumentation<MachineFunction, MachinePassInstrumentation>::requestAction( - MachinePassInstrumentation *Instrumentation, std::string_view Pass, std::string_view Rule, - const MachineFunction &Function, MachineInstrStableID Instruction, std::uint64_t Cost) { - return Instrumentation->requestAction(Pass, Rule, Function, Instruction, Cost); -} - -Expected<bool> -AnalysisManagerInstrumentation<MachineFunction, MachinePassInstrumentation>::requestAction( - MachinePassInstrumentation *Instrumentation, std::string_view Pass, std::string_view Rule, - const MachineFunction &Function, std::nullptr_t, std::uint64_t Cost) { - return Instrumentation->requestAction(Pass, Rule, Function, nullptr, Cost); -} - -void AnalysisManagerInstrumentation<CompilationUnit, MachinePassInstrumentation>::beforeAnalysis( - MachinePassInstrumentation *Instrumentation, std::string_view Name, - const CompilationUnit &Unit) { - Instrumentation->beforeAnalysis(Name, Unit); -} - -void AnalysisManagerInstrumentation<CompilationUnit, MachinePassInstrumentation>::afterAnalysis( - MachinePassInstrumentation *Instrumentation, std::string_view Name, const CompilationUnit &Unit, - bool CacheHit, std::uint64_t Nanoseconds) { - Instrumentation->afterAnalysis(Name, Unit, CacheHit, Nanoseconds); -} - -void AnalysisManagerInstrumentation<CompilationUnit, MachinePassInstrumentation>::analysisFailure( - MachinePassInstrumentation *Instrumentation, std::string_view Name, const CompilationUnit &Unit, - const Error &Failure, std::uint64_t Nanoseconds) { - Instrumentation->analysisFailure(Name, Unit, Failure, Nanoseconds); -} - -std::string MachineActionID::toString() const { - std::string Result; - Result.reserve(Pass.size() + Rule.size() + 48U); - Result.append(Pass); - Result.push_back(':'); - Result.append(Rule); - Result.append(":f"); - Result.append(std::to_string(Function.value())); - Result.append(":i"); - Result.append(std::to_string(Instruction.value())); - return Result; -} - -void MachinePassInstrumentation::addBeforeCallback(BeforeCallback Callback) { - if (!Callback) - return; - std::scoped_lock Lock(Mutex); - Before.push_back(std::move(Callback)); -} - -void MachinePassInstrumentation::addAfterCallback(AfterCallback Callback) { - if (!Callback) - return; - std::scoped_lock Lock(Mutex); - After.push_back(std::move(Callback)); -} - -void MachinePassInstrumentation::addFailureCallback(FailureCallback Callback) { - if (!Callback) - return; - std::scoped_lock Lock(Mutex); - Failure.push_back(std::move(Callback)); -} - -void MachinePassInstrumentation::addBeforeAnalysisCallback(BeforeAnalysisCallback Callback) { - if (!Callback) - return; - std::scoped_lock Lock(Mutex); - BeforeAnalysis.push_back(std::move(Callback)); -} - -void MachinePassInstrumentation::addAfterAnalysisCallback(AfterAnalysisCallback Callback) { - if (!Callback) - return; - std::scoped_lock Lock(Mutex); - AfterAnalysis.push_back(std::move(Callback)); -} - -void MachinePassInstrumentation::addAnalysisFailureCallback(AnalysisFailureCallback Callback) { - if (!Callback) - return; - std::scoped_lock Lock(Mutex); - AnalysisFailure.push_back(std::move(Callback)); -} - -void MachinePassInstrumentation::addIRPrintCallback(IRPrintCallback Callback) { - if (!Callback) - return; - std::scoped_lock Lock(Mutex); - IRPrint.push_back(std::move(Callback)); -} - -void MachinePassInstrumentation::addChangeCallback(ChangeCallback Callback) { - if (!Callback) - return; - std::scoped_lock Lock(Mutex); - Change.push_back(std::move(Callback)); -} - -void MachinePassInstrumentation::setActionFilter(ActionFilter NewFilter) { - std::scoped_lock Lock(Mutex); - Filter = std::move(NewFilter); -} - -void MachinePassInstrumentation::setPerFunctionFuel(std::optional<std::uint64_t> Fuel) { - std::scoped_lock Lock(Mutex); - PerFunctionFuel = Fuel; - ConsumedFuel.clear(); - ActionEvents.clear(); -} - -void MachinePassInstrumentation::addBeforeUnitCallback(BeforeUnitCallback Callback) { - if (!Callback) - return; - std::scoped_lock Lock(Mutex); - BeforeUnit.push_back(std::move(Callback)); -} - -void MachinePassInstrumentation::addAfterUnitCallback(AfterUnitCallback Callback) { - if (!Callback) - return; - std::scoped_lock Lock(Mutex); - AfterUnit.push_back(std::move(Callback)); -} - -void MachinePassInstrumentation::addUnitFailureCallback(UnitFailureCallback Callback) { - if (!Callback) - return; - std::scoped_lock Lock(Mutex); - UnitFailure.push_back(std::move(Callback)); -} - -void MachinePassInstrumentation::addBeforeUnitAnalysisCallback( - BeforeUnitAnalysisCallback Callback) { - if (!Callback) - return; - std::scoped_lock Lock(Mutex); - BeforeUnitAnalysis.push_back(std::move(Callback)); -} - -void MachinePassInstrumentation::addAfterUnitAnalysisCallback(AfterUnitAnalysisCallback Callback) { - if (!Callback) - return; - std::scoped_lock Lock(Mutex); - AfterUnitAnalysis.push_back(std::move(Callback)); -} - -void MachinePassInstrumentation::addUnitAnalysisFailureCallback( - UnitAnalysisFailureCallback Callback) { - if (!Callback) - return; - std::scoped_lock Lock(Mutex); - UnitAnalysisFailure.push_back(std::move(Callback)); -} - -InstrumentationStatistic &MachinePassInstrumentation::statistic(std::string_view Name, - bool IsAnalysis) const { - const std::string Key = std::string(IsAnalysis ? "analysis:" : "pass:") + std::string(Name); - auto [Position, Inserted] = Statistics.try_emplace(Key); - if (Inserted) { - Position->second.Name = std::string(Name); - Position->second.IsAnalysis = IsAnalysis; - } - return Position->second; -} - -void MachinePassInstrumentation::before(std::string_view Name, - const MachineFunction &Function) const { - std::vector<BeforeCallback> Callbacks; - std::vector<IRPrintCallback> Printers; - { - std::scoped_lock Lock(Mutex); - Callbacks = Before; - Printers = IRPrint; - } - for (const BeforeCallback &Callback : Callbacks) - Callback(Name, Function); - for (const IRPrintCallback &Printer : Printers) - Printer(InstrumentationPhase::Before, Name, Function); -} - -void MachinePassInstrumentation::after(std::string_view Name, const MachineFunction &Function, - const MachinePassResult &Result, - std::uint64_t Nanoseconds) const { - std::vector<AfterCallback> Callbacks; - std::vector<IRPrintCallback> Printers; - { - std::scoped_lock Lock(Mutex); - InstrumentationStatistic &Record = statistic(Name, false); - ++Record.Invocations; - Record.Changes += Result.Changed ? 1U : 0U; - Record.TotalNanoseconds += Nanoseconds; - Callbacks = After; - Printers = IRPrint; - } - for (const AfterCallback &Callback : Callbacks) - Callback(Name, Function, Result); - for (const IRPrintCallback &Printer : Printers) - Printer(InstrumentationPhase::After, Name, Function); -} - -void MachinePassInstrumentation::failure(std::string_view Name, const MachineFunction &Function, - const Error &ErrorValue, std::uint64_t Nanoseconds) const { - std::vector<FailureCallback> Callbacks; - { - std::scoped_lock Lock(Mutex); - InstrumentationStatistic &Record = statistic(Name, false); - ++Record.Invocations; - ++Record.Failures; - Record.TotalNanoseconds += Nanoseconds; - Callbacks = Failure; - } - for (const FailureCallback &Callback : Callbacks) - Callback(Name, Function, ErrorValue); -} - -void MachinePassInstrumentation::beforeAnalysis(std::string_view Name, - const MachineFunction &Function) const { - std::vector<BeforeAnalysisCallback> Callbacks; - { - std::scoped_lock Lock(Mutex); - Callbacks = BeforeAnalysis; - } - for (const BeforeAnalysisCallback &Callback : Callbacks) - Callback(Name, Function); -} - -void MachinePassInstrumentation::afterAnalysis(std::string_view Name, - const MachineFunction &Function, bool CacheHit, - std::uint64_t Nanoseconds) const { - std::vector<AfterAnalysisCallback> Callbacks; - { - std::scoped_lock Lock(Mutex); - InstrumentationStatistic &Record = statistic(Name, true); - ++Record.Invocations; - Record.CacheHits += CacheHit ? 1U : 0U; - Record.TotalNanoseconds += Nanoseconds; - Callbacks = AfterAnalysis; - } - for (const AfterAnalysisCallback &Callback : Callbacks) - Callback(Name, Function, CacheHit, Nanoseconds); -} - -void MachinePassInstrumentation::analysisFailure(std::string_view Name, - const MachineFunction &Function, - const Error &ErrorValue, - std::uint64_t Nanoseconds) const { - std::vector<AnalysisFailureCallback> Callbacks; - { - std::scoped_lock Lock(Mutex); - InstrumentationStatistic &Record = statistic(Name, true); - ++Record.Invocations; - ++Record.Failures; - Record.TotalNanoseconds += Nanoseconds; - Callbacks = AnalysisFailure; - } - for (const AnalysisFailureCallback &Callback : Callbacks) - Callback(Name, Function, ErrorValue); -} - -void MachinePassInstrumentation::change(std::string_view Name, const MachineFunction &Function, - MachinePassChanges Changes, bool FingerprintChanged) const { - std::vector<ChangeCallback> Callbacks; - { - std::scoped_lock Lock(Mutex); - Callbacks = Change; - } - for (const ChangeCallback &Callback : Callbacks) - Callback(Name, Function, Changes, FingerprintChanged); -} - -Expected<bool> MachinePassInstrumentation::requestAction(std::string_view Pass, - std::string_view Rule, - const MachineFunction &Function, - MachineInstrStableID Instruction, - std::uint64_t Cost) { - MachineActionID Action{ - .Pass = std::string(Pass), - .Rule = std::string(Rule), - .Function = Function.stableID(), - .Instruction = Instruction, - }; - if (Action.Pass.empty() || Action.Rule.empty() || Action.Function != Function.stableID() || - Cost == 0) { - return makeUnexpected(ErrorCode::InvalidArgument, "machine action identity is invalid"); - } - std::scoped_lock ActionLock(ActionMutex); - ActionFilter CurrentFilter; - { - std::scoped_lock Lock(Mutex); - CurrentFilter = Filter; - } - if (CurrentFilter && !CurrentFilter(Action, Cost)) { - std::scoped_lock Lock(Mutex); - ActionEvents.push_back({Action, Cost, false}); - return false; - } - - std::scoped_lock Lock(Mutex); - if (!PerFunctionFuel) { - ActionEvents.push_back({Action, Cost, true}); - return true; - } - std::uint64_t &Consumed = ConsumedFuel[Function.stableID().value()]; - if (Consumed > *PerFunctionFuel || Cost > *PerFunctionFuel - Consumed) { - ActionEvents.push_back({Action, Cost, false}); - return false; - } - Consumed += Cost; - ActionEvents.push_back({Action, Cost, true}); - return true; -} - -Expected<bool> MachinePassInstrumentation::requestAction(std::string_view Pass, - std::string_view Rule, - const MachineFunction &Function, - std::nullptr_t, std::uint64_t Cost) { - return requestAction(Pass, Rule, Function, MachineInstrStableID{}, Cost); -} - -void MachinePassInstrumentation::beforeUnit(std::string_view Name, - const CompilationUnit &Unit) const { - std::vector<BeforeUnitCallback> Callbacks; - { - std::scoped_lock Lock(Mutex); - Callbacks = BeforeUnit; - } - for (const BeforeUnitCallback &Callback : Callbacks) - Callback(Name, Unit); -} - -void MachinePassInstrumentation::afterUnit(std::string_view Name, const CompilationUnit &Unit, - const CompilationUnitPassResult &Result, - std::uint64_t Nanoseconds) const { - std::vector<AfterUnitCallback> Callbacks; - { - std::scoped_lock Lock(Mutex); - InstrumentationStatistic &Record = statistic("unit:" + std::string(Name), false); - ++Record.Invocations; - Record.Changes += Result.Changed ? 1U : 0U; - Record.TotalNanoseconds += Nanoseconds; - Callbacks = AfterUnit; - } - for (const AfterUnitCallback &Callback : Callbacks) - Callback(Name, Unit, Result); -} - -void MachinePassInstrumentation::unitFailure(std::string_view Name, const CompilationUnit &Unit, - const Error &ErrorValue, - std::uint64_t Nanoseconds) const { - std::vector<UnitFailureCallback> Callbacks; - { - std::scoped_lock Lock(Mutex); - InstrumentationStatistic &Record = statistic("unit:" + std::string(Name), false); - ++Record.Invocations; - ++Record.Failures; - Record.TotalNanoseconds += Nanoseconds; - Callbacks = UnitFailure; - } - for (const UnitFailureCallback &Callback : Callbacks) - Callback(Name, Unit, ErrorValue); -} - -void MachinePassInstrumentation::beforeAnalysis(std::string_view Name, - const CompilationUnit &Unit) const { - std::vector<BeforeUnitAnalysisCallback> Callbacks; - { - std::scoped_lock Lock(Mutex); - Callbacks = BeforeUnitAnalysis; - } - for (const BeforeUnitAnalysisCallback &Callback : Callbacks) - Callback(Name, Unit); -} - -void MachinePassInstrumentation::afterAnalysis(std::string_view Name, const CompilationUnit &Unit, - bool CacheHit, std::uint64_t Nanoseconds) const { - std::vector<AfterUnitAnalysisCallback> Callbacks; - { - std::scoped_lock Lock(Mutex); - InstrumentationStatistic &Record = statistic("unit:" + std::string(Name), true); - ++Record.Invocations; - Record.CacheHits += CacheHit ? 1U : 0U; - Record.TotalNanoseconds += Nanoseconds; - Callbacks = AfterUnitAnalysis; - } - for (const AfterUnitAnalysisCallback &Callback : Callbacks) - Callback(Name, Unit, CacheHit, Nanoseconds); -} - -void MachinePassInstrumentation::analysisFailure(std::string_view Name, const CompilationUnit &Unit, - const Error &ErrorValue, - std::uint64_t Nanoseconds) const { - std::vector<UnitAnalysisFailureCallback> Callbacks; - { - std::scoped_lock Lock(Mutex); - InstrumentationStatistic &Record = statistic("unit:" + std::string(Name), true); - ++Record.Invocations; - ++Record.Failures; - Record.TotalNanoseconds += Nanoseconds; - Callbacks = UnitAnalysisFailure; - } - for (const UnitAnalysisFailureCallback &Callback : Callbacks) - Callback(Name, Unit, ErrorValue); -} - -std::vector<InstrumentationStatistic> MachinePassInstrumentation::statistics() const { - std::vector<InstrumentationStatistic> Result; - { - std::scoped_lock Lock(Mutex); - Result.reserve(Statistics.size()); - for (const auto &[Key, Record] : Statistics) { - (void)Key; - Result.push_back(Record); - } - } - std::ranges::sort( - Result, [](const InstrumentationStatistic &Left, const InstrumentationStatistic &Right) { - if (Left.IsAnalysis != Right.IsAnalysis) - return Left.IsAnalysis < Right.IsAnalysis; - return Left.Name < Right.Name; - }); - return Result; -} - -std::vector<MachineActionEvent> MachinePassInstrumentation::actionEvents() const { - std::vector<MachineActionEvent> Result; - { - std::scoped_lock Lock(Mutex); - Result = ActionEvents; - } - std::ranges::sort(Result, [](const MachineActionEvent &Left, const MachineActionEvent &Right) { - if (Left.ID.Function.value() != Right.ID.Function.value()) - return Left.ID.Function.value() < Right.ID.Function.value(); - if (Left.ID.Instruction.value() != Right.ID.Instruction.value()) - return Left.ID.Instruction.value() < Right.ID.Instruction.value(); - if (Left.ID.Pass != Right.ID.Pass) - return Left.ID.Pass < Right.ID.Pass; - if (Left.ID.Rule != Right.ID.Rule) - return Left.ID.Rule < Right.ID.Rule; - if (Left.Cost != Right.Cost) - return Left.Cost < Right.Cost; - return Left.Accepted < Right.Accepted; - }); - return Result; -} - -bool MachinePassInstrumentation::requiresSerialFunctionExecution() const { - std::scoped_lock Lock(Mutex); - return !Before.empty() || !After.empty() || !Failure.empty() || !BeforeAnalysis.empty() || - !AfterAnalysis.empty() || !AnalysisFailure.empty() || !IRPrint.empty() || !Change.empty(); -} - Expected<void> PassManagerCallbacks<MachineFunction, MachineFunctionPass, MachinePassManagerOptions>::validate( const MachineFunctionPass &Pass) { diff --git a/backend/lib/IR/CMakeLists.txt b/backend/lib/IR/CMakeLists.txt index a53cc96..b903164 100644 --- a/backend/lib/IR/CMakeLists.txt +++ b/backend/lib/IR/CMakeLists.txt @@ -5,6 +5,7 @@ set( RCCBackendIRHeaders "${RCC_BACKEND_SOURCE_DIR}/include/rcc/IR/Constants.h" "${RCC_BACKEND_SOURCE_DIR}/include/rcc/IR/DataLayout.h" + "${RCC_BACKEND_SOURCE_DIR}/include/rcc/IR/PassInstrumentation.h" ) add_library(RCCBackendIR ${RCCBackendIRSources}) |
