aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard-Qin-X <richard.qin.001@gmail.com>2026-08-28 13:58:47 +0800
committerRichard-Qin-X <richard.qin.001@gmail.com>2026-08-28 13:58:47 +0800
commit8c878ada4e1df8b37aea9ff44a5fb2b25d2b2a1f (patch)
treec2c3ac9221550719b7f873de333ec6803f284a7e
parent4813e41cb6765e1b87acf12c485f75c04c1938ff (diff)
downloadrcc-project-8c878ada4e1df8b37aea9ff44a5fb2b25d2b2a1f.tar.gz
rcc-project-8c878ada4e1df8b37aea9ff44a5fb2b25d2b2a1f.tar.xz
[CodeGen] Separate pass instrumentation ownership
-rw-r--r--backend/include/rcc/CodeGen/MachinePassInstrumentation.h153
-rw-r--r--backend/include/rcc/CodeGen/MachinePassManager.h2
-rw-r--r--backend/include/rcc/IR/PassInstrumentation.h219
-rw-r--r--backend/lib/CodeGen/CMakeLists.txt3
-rw-r--r--backend/lib/CodeGen/MachinePassInstrumentation.cpp407
-rw-r--r--backend/lib/CodeGen/MachinePassManager.cpp475
-rw-r--r--backend/lib/IR/CMakeLists.txt1
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})