aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backend/include/rcc/CodeGen/GlobalISel/InstructionSelect.h4
-rw-r--r--backend/include/rcc/CodeGen/GlobalISel/Legalizer.h4
-rw-r--r--backend/include/rcc/CodeGen/GlobalISel/RegBankSelect.h4
-rw-r--r--backend/include/rcc/CodeGen/LiveIntervals.h7
-rw-r--r--backend/include/rcc/CodeGen/LiveVariables.h12
-rw-r--r--backend/include/rcc/CodeGen/MachineAnalyses.h35
-rw-r--r--backend/include/rcc/CodeGen/MachineBlockPlacement.h11
-rw-r--r--backend/include/rcc/CodeGen/MachineBranchOptimization.h4
-rw-r--r--backend/include/rcc/CodeGen/MachineBranchRelaxation.h4
-rw-r--r--backend/include/rcc/CodeGen/MachineCSE.h10
-rw-r--r--backend/include/rcc/CodeGen/MachineCombiner.h4
-rw-r--r--backend/include/rcc/CodeGen/MachineCopyPropagation.h4
-rw-r--r--backend/include/rcc/CodeGen/MachineDCE.h4
-rw-r--r--backend/include/rcc/CodeGen/MachineFallthrough.h4
-rw-r--r--backend/include/rcc/CodeGen/MachineFinalization.h6
-rw-r--r--backend/include/rcc/CodeGen/MachineFunctionAnalysisManager.h133
-rw-r--r--backend/include/rcc/CodeGen/MachineLICM.h10
-rw-r--r--backend/include/rcc/CodeGen/MachineMemoryFolding.h4
-rw-r--r--backend/include/rcc/CodeGen/MachineOptimizationPipeline.h11
-rw-r--r--backend/include/rcc/CodeGen/MachinePass.h720
-rw-r--r--backend/include/rcc/CodeGen/MachinePassManager.h134
-rw-r--r--backend/include/rcc/CodeGen/MachinePseudoExpansion.h10
-rw-r--r--backend/include/rcc/CodeGen/MachineScheduler.h4
-rw-r--r--backend/include/rcc/CodeGen/MachineShrinkWrapping.h4
-rw-r--r--backend/include/rcc/CodeGen/MachineSink.h8
-rw-r--r--backend/include/rcc/CodeGen/MachineStackSlotColoring.h4
-rw-r--r--backend/include/rcc/CodeGen/MachineTailDuplication.h4
-rw-r--r--backend/include/rcc/CodeGen/MachineTailMerge.h4
-rw-r--r--backend/include/rcc/CodeGen/PHIElimination.h4
-rw-r--r--backend/include/rcc/CodeGen/PostRAScheduler.h4
-rw-r--r--backend/include/rcc/CodeGen/PrologueEpilogueInsertion.h4
-rw-r--r--backend/include/rcc/CodeGen/RegAllocCommon.h2
-rw-r--r--backend/include/rcc/CodeGen/RegAllocFast.h4
-rw-r--r--backend/include/rcc/CodeGen/RegAllocPBQP.h2
-rw-r--r--backend/include/rcc/CodeGen/SlotIndexes.h7
-rw-r--r--backend/include/rcc/CodeGen/TwoAddressInstructionPass.h4
-rw-r--r--backend/include/rcc/CodeGen/VirtRegMap.h4
-rw-r--r--backend/include/rcc/IR/PassInstrumentation.h227
-rw-r--r--backend/include/rcc/IR/PassManager.h531
-rw-r--r--backend/include/rcc/Target/RISCV/RISCVPipeline.h4
-rw-r--r--backend/include/rcc/Tooling/BackendDriver.h2
-rw-r--r--backend/include/rcc/Tooling/PipelineDriver.h2
-rw-r--r--backend/lib/CodeGen/CMakeLists.txt11
-rw-r--r--backend/lib/CodeGen/GlobalISel/InstructionSelect.cpp2
-rw-r--r--backend/lib/CodeGen/GlobalISel/Legalizer.cpp2
-rw-r--r--backend/lib/CodeGen/GlobalISel/RegBankSelect.cpp2
-rw-r--r--backend/lib/CodeGen/InlineSpiller.cpp2
-rw-r--r--backend/lib/CodeGen/LiveIntervals.cpp4
-rw-r--r--backend/lib/CodeGen/LiveVariables.cpp27
-rw-r--r--backend/lib/CodeGen/MachineAnalyses.cpp48
-rw-r--r--backend/lib/CodeGen/MachineBlockPlacement.cpp20
-rw-r--r--backend/lib/CodeGen/MachineBranchOptimization.cpp2
-rw-r--r--backend/lib/CodeGen/MachineBranchRelaxation.cpp6
-rw-r--r--backend/lib/CodeGen/MachineCSE.cpp12
-rw-r--r--backend/lib/CodeGen/MachineCombiner.cpp2
-rw-r--r--backend/lib/CodeGen/MachineCopyPropagation.cpp6
-rw-r--r--backend/lib/CodeGen/MachineDCE.cpp2
-rw-r--r--backend/lib/CodeGen/MachineFallthrough.cpp6
-rw-r--r--backend/lib/CodeGen/MachineFinalization.cpp4
-rw-r--r--backend/lib/CodeGen/MachineLICM.cpp22
-rw-r--r--backend/lib/CodeGen/MachineMemoryFolding.cpp2
-rw-r--r--backend/lib/CodeGen/MachineOptimizationPipeline.cpp10
-rw-r--r--backend/lib/CodeGen/MachinePassManager.cpp (renamed from backend/lib/CodeGen/MachinePass.cpp)608
-rw-r--r--backend/lib/CodeGen/MachinePseudoExpansion.cpp26
-rw-r--r--backend/lib/CodeGen/MachineScheduler.cpp9
-rw-r--r--backend/lib/CodeGen/MachineShrinkWrapping.cpp10
-rw-r--r--backend/lib/CodeGen/MachineSink.cpp18
-rw-r--r--backend/lib/CodeGen/MachineStackSlotColoring.cpp2
-rw-r--r--backend/lib/CodeGen/MachineTailDuplication.cpp2
-rw-r--r--backend/lib/CodeGen/MachineTailMerge.cpp2
-rw-r--r--backend/lib/CodeGen/PHIElimination.cpp2
-rw-r--r--backend/lib/CodeGen/PostRAScheduler.cpp9
-rw-r--r--backend/lib/CodeGen/PrologueEpilogueInsertion.cpp2
-rw-r--r--backend/lib/CodeGen/RegAllocBase.h7
-rw-r--r--backend/lib/CodeGen/RegAllocBasic.cpp8
-rw-r--r--backend/lib/CodeGen/RegAllocBasic.h2
-rw-r--r--backend/lib/CodeGen/RegAllocFast.cpp6
-rw-r--r--backend/lib/CodeGen/RegAllocPBQP.cpp8
-rw-r--r--backend/lib/CodeGen/SlotIndexes.cpp4
-rw-r--r--backend/lib/CodeGen/TwoAddressInstructionPass.cpp6
-rw-r--r--backend/lib/CodeGen/VirtRegMap.cpp4
-rw-r--r--backend/lib/Target/RISCV/RISCVPipeline.cpp22
-rw-r--r--backend/lib/Tooling/PipelineDriver.cpp8
-rw-r--r--backend/unittests/CodeGen/CMakeLists.txt41
-rw-r--r--backend/unittests/CodeGen/GlobalISel/InstructionSelectTest.cpp14
-rw-r--r--backend/unittests/CodeGen/GlobalISel/LegalizerTest.cpp10
-rw-r--r--backend/unittests/CodeGen/GlobalISel/RegBankSelectTest.cpp4
-rw-r--r--backend/unittests/CodeGen/LiveIntervalTest.cpp2
-rw-r--r--backend/unittests/CodeGen/LiveIntervalsTest.cpp8
-rw-r--r--backend/unittests/CodeGen/LivePhysRegsTest.cpp2
-rw-r--r--backend/unittests/CodeGen/LiveRegMatrixTest.cpp4
-rw-r--r--backend/unittests/CodeGen/LiveVariablesTest.cpp26
-rw-r--r--backend/unittests/CodeGen/MachineAnalysesTest.cpp24
-rw-r--r--backend/unittests/CodeGen/MachineOptimizationTest.cpp20
-rw-r--r--backend/unittests/CodeGen/MachinePassManagerTest.cpp426
-rw-r--r--backend/unittests/CodeGen/MachinePassTest.cpp918
-rw-r--r--backend/unittests/CodeGen/MachineSchedulingTest.cpp8
-rw-r--r--backend/unittests/CodeGen/PHIEliminationTest.cpp8
-rw-r--r--backend/unittests/CodeGen/PassInstrumentationTest.cpp173
-rw-r--r--backend/unittests/CodeGen/PassManagerTest.cpp260
-rw-r--r--backend/unittests/CodeGen/RegisterAllocationTest.cpp14
-rw-r--r--backend/unittests/CodeGen/RegisterAllocationTestSupport.h4
-rw-r--r--backend/unittests/CodeGen/SlotIndexesTest.cpp2
-rw-r--r--backend/unittests/CodeGen/TwoAddressInstructionPassTest.cpp8
-rw-r--r--backend/unittests/Target/RISCVFrameLoweringTest.cpp6
-rw-r--r--backend/unittests/Target/RISCVLateCodeGenTest.cpp50
-rw-r--r--backend/unittests/Target/RISCVRegisterAllocationTest.cpp6
-rw-r--r--backend/unittests/Target/RISCVSSAExitTest.cpp6
108 files changed, 2435 insertions, 2534 deletions
diff --git a/backend/include/rcc/CodeGen/GlobalISel/InstructionSelect.h b/backend/include/rcc/CodeGen/GlobalISel/InstructionSelect.h
index 0c034cd..f342cdc 100644
--- a/backend/include/rcc/CodeGen/GlobalISel/InstructionSelect.h
+++ b/backend/include/rcc/CodeGen/GlobalISel/InstructionSelect.h
@@ -4,7 +4,7 @@
#define RCC_CODEGEN_GLOBALISEL_INSTRUCTIONSELECT_H
#include "rcc/CodeGen/GlobalISel/InstructionSelector.h"
-#include "rcc/CodeGen/MachinePass.h"
+#include "rcc/CodeGen/MachinePassManager.h"
namespace rcc {
@@ -16,7 +16,7 @@ public:
[[nodiscard]] const MachinePassContract &contract() const noexcept override;
[[nodiscard]] Expected<MachinePassResult> run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &Analyses) override;
+ MachineFunctionAnalysisManager &Analyses) override;
private:
[[nodiscard]] Expected<MachinePassResult> runImplementation(MachineFunction &Function,
diff --git a/backend/include/rcc/CodeGen/GlobalISel/Legalizer.h b/backend/include/rcc/CodeGen/GlobalISel/Legalizer.h
index 7f86d16..dfeda22 100644
--- a/backend/include/rcc/CodeGen/GlobalISel/Legalizer.h
+++ b/backend/include/rcc/CodeGen/GlobalISel/Legalizer.h
@@ -4,7 +4,7 @@
#define RCC_CODEGEN_GLOBALISEL_LEGALIZER_H
#include "rcc/CodeGen/GlobalISel/LegalizerInfo.h"
-#include "rcc/CodeGen/MachinePass.h"
+#include "rcc/CodeGen/MachinePassManager.h"
#include <memory>
@@ -20,7 +20,7 @@ public:
[[nodiscard]] const MachinePassContract &contract() const noexcept override;
[[nodiscard]] Expected<MachinePassResult> run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &Analyses) override;
+ MachineFunctionAnalysisManager &Analyses) override;
private:
[[nodiscard]] Expected<MachinePassResult> runImplementation(MachineFunction &Function,
diff --git a/backend/include/rcc/CodeGen/GlobalISel/RegBankSelect.h b/backend/include/rcc/CodeGen/GlobalISel/RegBankSelect.h
index 256d748..a7fc6bf 100644
--- a/backend/include/rcc/CodeGen/GlobalISel/RegBankSelect.h
+++ b/backend/include/rcc/CodeGen/GlobalISel/RegBankSelect.h
@@ -3,7 +3,7 @@
#ifndef RCC_CODEGEN_GLOBALISEL_REGBANKSELECT_H
#define RCC_CODEGEN_GLOBALISEL_REGBANKSELECT_H
-#include "rcc/CodeGen/MachinePass.h"
+#include "rcc/CodeGen/MachinePassManager.h"
#include "rcc/CodeGen/RegisterBankInfo.h"
namespace rcc {
@@ -16,7 +16,7 @@ public:
[[nodiscard]] const MachinePassContract &contract() const noexcept override;
[[nodiscard]] Expected<MachinePassResult> run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &Analyses) override;
+ MachineFunctionAnalysisManager &Analyses) override;
private:
const RegisterBankInfo *Info;
diff --git a/backend/include/rcc/CodeGen/LiveIntervals.h b/backend/include/rcc/CodeGen/LiveIntervals.h
index a45c593..b5ba05a 100644
--- a/backend/include/rcc/CodeGen/LiveIntervals.h
+++ b/backend/include/rcc/CodeGen/LiveIntervals.h
@@ -4,7 +4,7 @@
#define RCC_CODEGEN_LIVEINTERVALS_H
#include "rcc/CodeGen/LiveInterval.h"
-#include "rcc/CodeGen/MachinePass.h"
+#include "rcc/CodeGen/MachinePassManager.h"
#include "rcc/CodeGen/RegisterMask.h"
#include <cstdint>
@@ -64,8 +64,9 @@ public:
return "LiveIntervals";
}
- [[nodiscard]] static Expected<Result>
- run(MachineFunction &Function, const TargetDescription &Target, MachineAnalysisManager &Analyses);
+ [[nodiscard]] static Expected<Result> run(MachineFunction &Function,
+ const TargetDescription &Target,
+ MachineFunctionAnalysisManager &Analyses);
};
} // namespace rcc
diff --git a/backend/include/rcc/CodeGen/LiveVariables.h b/backend/include/rcc/CodeGen/LiveVariables.h
index 28a66c1..c95e7d8 100644
--- a/backend/include/rcc/CodeGen/LiveVariables.h
+++ b/backend/include/rcc/CodeGen/LiveVariables.h
@@ -4,7 +4,7 @@
#define RCC_CODEGEN_LIVEVARIABLES_H
#include "rcc/CodeGen/LiveRegUnits.h"
-#include "rcc/CodeGen/MachinePass.h"
+#include "rcc/CodeGen/MachinePassManager.h"
#include "rcc/CodeGen/Register.h"
#include "rcc/Support/Error.h"
@@ -82,8 +82,9 @@ public:
return "LiveVariables";
}
- [[nodiscard]] static Expected<Result>
- run(MachineFunction &Function, const TargetDescription &Target, MachineAnalysisManager &Analyses);
+ [[nodiscard]] static Expected<Result> run(MachineFunction &Function,
+ const TargetDescription &Target,
+ MachineFunctionAnalysisManager &Analyses);
};
class RebuildMachineLivenessPass final : public MachineFunctionPass {
@@ -91,14 +92,15 @@ public:
[[nodiscard]] const MachinePassContract &contract() const noexcept override;
[[nodiscard]] Expected<MachinePassResult> run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &Analyses) override;
+ MachineFunctionAnalysisManager &Analyses) override;
};
[[nodiscard]] Expected<void> verifyTrackedMachineLiveness(const MachineFunction &Function,
const TargetDescription &Target);
[[nodiscard]] Expected<bool> rebuildMachineLiveness(MachineFunction &Function,
const TargetDescription &Target);
-[[nodiscard]] Expected<void> registerStage11MachineAnalyses(MachineAnalysisManager &Analyses);
+[[nodiscard]] Expected<void>
+registerStage11MachineAnalyses(MachineFunctionAnalysisManager &Analyses);
} // namespace rcc
diff --git a/backend/include/rcc/CodeGen/MachineAnalyses.h b/backend/include/rcc/CodeGen/MachineAnalyses.h
index eda550d..4adb300 100644
--- a/backend/include/rcc/CodeGen/MachineAnalyses.h
+++ b/backend/include/rcc/CodeGen/MachineAnalyses.h
@@ -5,7 +5,7 @@
#include "rcc/CodeGen/MachineBasicBlock.h"
#include "rcc/CodeGen/MachineIRTypes.h"
-#include "rcc/CodeGen/MachinePass.h"
+#include "rcc/CodeGen/MachinePassManager.h"
#include "rcc/CodeGen/StableID.h"
#include "rcc/Support/Error.h"
@@ -62,8 +62,9 @@ public:
return "MachineDominatorTree";
}
- [[nodiscard]] static Expected<Result>
- run(MachineFunction &Function, const TargetDescription &Target, MachineAnalysisManager &Analyses);
+ [[nodiscard]] static Expected<Result> run(MachineFunction &Function,
+ const TargetDescription &Target,
+ MachineFunctionAnalysisManager &Analyses);
};
struct MachineLoop final {
@@ -107,8 +108,9 @@ public:
return "MachineLoopInfo";
}
- [[nodiscard]] static Expected<Result>
- run(MachineFunction &Function, const TargetDescription &Target, MachineAnalysisManager &Analyses);
+ [[nodiscard]] static Expected<Result> run(MachineFunction &Function,
+ const TargetDescription &Target,
+ MachineFunctionAnalysisManager &Analyses);
};
class MachineBranchProbabilityAnalysis final {
@@ -130,8 +132,9 @@ public:
return "MachineBranchProbability";
}
- [[nodiscard]] static Expected<Result>
- run(MachineFunction &Function, const TargetDescription &Target, MachineAnalysisManager &Analyses);
+ [[nodiscard]] static Expected<Result> run(MachineFunction &Function,
+ const TargetDescription &Target,
+ MachineFunctionAnalysisManager &Analyses);
};
class MachineBlockFrequencyAnalysis final {
@@ -152,8 +155,9 @@ public:
return "MachineBlockFrequency";
}
- [[nodiscard]] static Expected<Result>
- run(MachineFunction &Function, const TargetDescription &Target, MachineAnalysisManager &Analyses);
+ [[nodiscard]] static Expected<Result> run(MachineFunction &Function,
+ const TargetDescription &Target,
+ MachineFunctionAnalysisManager &Analyses);
};
enum class MachineAliasResult : std::uint8_t {
@@ -175,8 +179,9 @@ public:
return "MachineAliasAnalysis";
}
- [[nodiscard]] static Expected<Result>
- run(MachineFunction &Function, const TargetDescription &Target, MachineAnalysisManager &Analyses);
+ [[nodiscard]] static Expected<Result> run(MachineFunction &Function,
+ const TargetDescription &Target,
+ MachineFunctionAnalysisManager &Analyses);
};
enum class MachineMemoryDependencyKind : std::uint8_t {
@@ -233,11 +238,13 @@ public:
return "MachineMemoryDependence";
}
- [[nodiscard]] static Expected<Result>
- run(MachineFunction &Function, const TargetDescription &Target, MachineAnalysisManager &Analyses);
+ [[nodiscard]] static Expected<Result> run(MachineFunction &Function,
+ const TargetDescription &Target,
+ MachineFunctionAnalysisManager &Analyses);
};
-[[nodiscard]] Expected<void> registerStage8MachineAnalyses(MachineAnalysisManager &Analyses);
+[[nodiscard]] Expected<void>
+registerStage8MachineAnalyses(MachineFunctionAnalysisManager &Analyses);
} // namespace rcc
diff --git a/backend/include/rcc/CodeGen/MachineBlockPlacement.h b/backend/include/rcc/CodeGen/MachineBlockPlacement.h
index 52ddafd..41d5f2d 100644
--- a/backend/include/rcc/CodeGen/MachineBlockPlacement.h
+++ b/backend/include/rcc/CodeGen/MachineBlockPlacement.h
@@ -3,7 +3,7 @@
#ifndef RCC_CODEGEN_MACHINEBLOCKPLACEMENT_H
#define RCC_CODEGEN_MACHINEBLOCKPLACEMENT_H
-#include "rcc/CodeGen/MachinePass.h"
+#include "rcc/CodeGen/MachinePassManager.h"
namespace rcc {
@@ -12,13 +12,12 @@ public:
[[nodiscard]] const MachinePassContract &contract() const noexcept override;
[[nodiscard]] Expected<MachinePassResult> run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &Analyses) override;
+ MachineFunctionAnalysisManager &Analyses) override;
private:
- [[nodiscard]] Expected<MachinePassResult> runImplementation(MachineFunction &Function,
- const TargetDescription &Target,
- MachineAnalysisManager &Analyses,
- MachineActionReplay &Actions) const;
+ [[nodiscard]] Expected<MachinePassResult>
+ runImplementation(MachineFunction &Function, const TargetDescription &Target,
+ MachineFunctionAnalysisManager &Analyses, MachineActionReplay &Actions) const;
};
} // namespace rcc
diff --git a/backend/include/rcc/CodeGen/MachineBranchOptimization.h b/backend/include/rcc/CodeGen/MachineBranchOptimization.h
index 9f120dc..e578d72 100644
--- a/backend/include/rcc/CodeGen/MachineBranchOptimization.h
+++ b/backend/include/rcc/CodeGen/MachineBranchOptimization.h
@@ -3,7 +3,7 @@
#ifndef RCC_CODEGEN_MACHINEBRANCHOPTIMIZATION_H
#define RCC_CODEGEN_MACHINEBRANCHOPTIMIZATION_H
-#include "rcc/CodeGen/MachinePass.h"
+#include "rcc/CodeGen/MachinePassManager.h"
#include <cstddef>
@@ -24,7 +24,7 @@ public:
[[nodiscard]] const MachinePassContract &contract() const noexcept override;
[[nodiscard]] Expected<MachinePassResult> run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &Analyses) override;
+ MachineFunctionAnalysisManager &Analyses) override;
private:
[[nodiscard]] Expected<MachinePassResult>
diff --git a/backend/include/rcc/CodeGen/MachineBranchRelaxation.h b/backend/include/rcc/CodeGen/MachineBranchRelaxation.h
index 03c7fa7..5b359b4 100644
--- a/backend/include/rcc/CodeGen/MachineBranchRelaxation.h
+++ b/backend/include/rcc/CodeGen/MachineBranchRelaxation.h
@@ -3,7 +3,7 @@
#ifndef RCC_CODEGEN_MACHINEBRANCHRELAXATION_H
#define RCC_CODEGEN_MACHINEBRANCHRELAXATION_H
-#include "rcc/CodeGen/MachinePass.h"
+#include "rcc/CodeGen/MachinePassManager.h"
#include <cstddef>
@@ -24,7 +24,7 @@ public:
[[nodiscard]] const MachinePassContract &contract() const noexcept override;
[[nodiscard]] Expected<MachinePassResult> run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &Analyses) override;
+ MachineFunctionAnalysisManager &Analyses) override;
private:
[[nodiscard]] Expected<MachinePassResult> runImplementation(MachineFunction &Function,
diff --git a/backend/include/rcc/CodeGen/MachineCSE.h b/backend/include/rcc/CodeGen/MachineCSE.h
index 1c2057b..dc10b62 100644
--- a/backend/include/rcc/CodeGen/MachineCSE.h
+++ b/backend/include/rcc/CodeGen/MachineCSE.h
@@ -3,7 +3,7 @@
#ifndef RCC_CODEGEN_MACHINECSE_H
#define RCC_CODEGEN_MACHINECSE_H
-#include "rcc/CodeGen/MachinePass.h"
+#include "rcc/CodeGen/MachinePassManager.h"
#include <cstddef>
@@ -20,12 +20,12 @@ public:
[[nodiscard]] const MachinePassContract &contract() const noexcept override;
[[nodiscard]] Expected<MachinePassResult> run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &Analyses) override;
+ MachineFunctionAnalysisManager &Analyses) override;
private:
- [[nodiscard]] Expected<MachinePassResult> runImplementation(MachineFunction &Function,
- const TargetDescription &Target,
- MachineAnalysisManager &Analyses);
+ [[nodiscard]] Expected<MachinePassResult>
+ runImplementation(MachineFunction &Function, const TargetDescription &Target,
+ MachineFunctionAnalysisManager &Analyses);
MachineCSEOptions Options;
};
diff --git a/backend/include/rcc/CodeGen/MachineCombiner.h b/backend/include/rcc/CodeGen/MachineCombiner.h
index ef7f432..3850b91 100644
--- a/backend/include/rcc/CodeGen/MachineCombiner.h
+++ b/backend/include/rcc/CodeGen/MachineCombiner.h
@@ -4,7 +4,7 @@
#define RCC_CODEGEN_MACHINECOMBINER_H
#include "rcc/CodeGen/MachineCombinerPattern.h"
-#include "rcc/CodeGen/MachinePass.h"
+#include "rcc/CodeGen/MachinePassManager.h"
#include <cstddef>
@@ -24,7 +24,7 @@ public:
[[nodiscard]] const MachinePassContract &contract() const noexcept override;
[[nodiscard]] Expected<MachinePassResult> run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &Analyses) override;
+ MachineFunctionAnalysisManager &Analyses) override;
private:
[[nodiscard]] Expected<MachinePassResult> runImplementation(MachineFunction &Function,
diff --git a/backend/include/rcc/CodeGen/MachineCopyPropagation.h b/backend/include/rcc/CodeGen/MachineCopyPropagation.h
index 43baa7e..ab8b23f 100644
--- a/backend/include/rcc/CodeGen/MachineCopyPropagation.h
+++ b/backend/include/rcc/CodeGen/MachineCopyPropagation.h
@@ -3,7 +3,7 @@
#ifndef RCC_CODEGEN_MACHINECOPYPROPAGATION_H
#define RCC_CODEGEN_MACHINECOPYPROPAGATION_H
-#include "rcc/CodeGen/MachinePass.h"
+#include "rcc/CodeGen/MachinePassManager.h"
#include <cstddef>
#include <cstdint>
@@ -30,7 +30,7 @@ public:
[[nodiscard]] const MachinePassContract &contract() const noexcept override;
[[nodiscard]] Expected<MachinePassResult> run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &Analyses) override;
+ MachineFunctionAnalysisManager &Analyses) override;
private:
[[nodiscard]] Expected<MachinePassResult> runImplementation(MachineFunction &Function,
diff --git a/backend/include/rcc/CodeGen/MachineDCE.h b/backend/include/rcc/CodeGen/MachineDCE.h
index 893108d..8860b0f 100644
--- a/backend/include/rcc/CodeGen/MachineDCE.h
+++ b/backend/include/rcc/CodeGen/MachineDCE.h
@@ -3,7 +3,7 @@
#ifndef RCC_CODEGEN_MACHINEDCE_H
#define RCC_CODEGEN_MACHINEDCE_H
-#include "rcc/CodeGen/MachinePass.h"
+#include "rcc/CodeGen/MachinePassManager.h"
namespace rcc {
@@ -12,7 +12,7 @@ public:
[[nodiscard]] const MachinePassContract &contract() const noexcept override;
[[nodiscard]] Expected<MachinePassResult> run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &Analyses) override;
+ MachineFunctionAnalysisManager &Analyses) override;
private:
[[nodiscard]] Expected<MachinePassResult> runImplementation(MachineFunction &Function,
diff --git a/backend/include/rcc/CodeGen/MachineFallthrough.h b/backend/include/rcc/CodeGen/MachineFallthrough.h
index 5793330..bb62e8a 100644
--- a/backend/include/rcc/CodeGen/MachineFallthrough.h
+++ b/backend/include/rcc/CodeGen/MachineFallthrough.h
@@ -3,7 +3,7 @@
#ifndef RCC_CODEGEN_MACHINEFALLTHROUGH_H
#define RCC_CODEGEN_MACHINEFALLTHROUGH_H
-#include "rcc/CodeGen/MachinePass.h"
+#include "rcc/CodeGen/MachinePassManager.h"
namespace rcc {
@@ -16,7 +16,7 @@ public:
[[nodiscard]] const MachinePassContract &contract() const noexcept override;
[[nodiscard]] Expected<MachinePassResult> run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &Analyses) override;
+ MachineFunctionAnalysisManager &Analyses) override;
private:
const TargetInstrInfo *Info;
diff --git a/backend/include/rcc/CodeGen/MachineFinalization.h b/backend/include/rcc/CodeGen/MachineFinalization.h
index 1927691..d12ee0b 100644
--- a/backend/include/rcc/CodeGen/MachineFinalization.h
+++ b/backend/include/rcc/CodeGen/MachineFinalization.h
@@ -3,7 +3,7 @@
#ifndef RCC_CODEGEN_MACHINEFINALIZATION_H
#define RCC_CODEGEN_MACHINEFINALIZATION_H
-#include "rcc/CodeGen/MachinePass.h"
+#include "rcc/CodeGen/MachinePassManager.h"
namespace rcc {
@@ -14,7 +14,7 @@ public:
[[nodiscard]] const MachinePassContract &contract() const noexcept override;
[[nodiscard]] Expected<MachinePassResult> run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &Analyses) override;
+ MachineFunctionAnalysisManager &Analyses) override;
};
class FinalEncodabilityVerifierPass final : public MachineFunctionPass {
@@ -25,7 +25,7 @@ public:
[[nodiscard]] const MachinePassContract &contract() const noexcept override;
[[nodiscard]] Expected<MachinePassResult> run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &Analyses) override;
+ MachineFunctionAnalysisManager &Analyses) override;
private:
const TargetInstrInfo *BranchInfo;
diff --git a/backend/include/rcc/CodeGen/MachineFunctionAnalysisManager.h b/backend/include/rcc/CodeGen/MachineFunctionAnalysisManager.h
new file mode 100644
index 0000000..9685e45
--- /dev/null
+++ b/backend/include/rcc/CodeGen/MachineFunctionAnalysisManager.h
@@ -0,0 +1,133 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef RCC_CODEGEN_MACHINEFUNCTIONANALYSISMANAGER_H
+#define RCC_CODEGEN_MACHINEFUNCTIONANALYSISMANAGER_H
+
+#include "rcc/CodeGen/StableID.h"
+#include "rcc/IR/PassManager.h"
+
+#include <cstdint>
+#include <initializer_list>
+
+namespace rcc {
+
+class CompilationUnit;
+class MachineFunction;
+class MachinePassInstrumentation;
+
+enum class MachinePassChange : std::uint32_t {
+ None = 0,
+ Instructions = 1U << 0U,
+ Operands = 1U << 1U,
+ Registers = 1U << 2U,
+ CFG = 1U << 3U,
+ BlockLayout = 1U << 4U,
+ Frame = 1U << 5U,
+ ConstantPool = 1U << 6U,
+ JumpTable = 1U << 7U,
+ TargetState = 1U << 8U,
+};
+
+class MachinePassChanges final {
+public:
+ constexpr MachinePassChanges() noexcept = default;
+ constexpr MachinePassChanges(std::initializer_list<MachinePassChange> Changes) noexcept {
+ for (const MachinePassChange Change : Changes)
+ add(Change);
+ }
+
+ [[nodiscard]] static constexpr MachinePassChanges all() noexcept {
+ return fromRaw((1U << 9U) - 1U);
+ }
+
+ [[nodiscard]] static constexpr MachinePassChanges fromRaw(std::uint32_t Bits) noexcept {
+ MachinePassChanges Result;
+ Result.Bits = Bits & rawMask();
+ return Result;
+ }
+
+ constexpr void add(MachinePassChange Change) noexcept {
+ Bits |= static_cast<std::uint32_t>(Change);
+ }
+
+ [[nodiscard]] constexpr bool has(MachinePassChange Change) const noexcept {
+ return (Bits & static_cast<std::uint32_t>(Change)) != 0;
+ }
+
+ [[nodiscard]] constexpr bool contains(MachinePassChanges Other) const noexcept {
+ return (Bits & Other.Bits) == Other.Bits;
+ }
+
+ [[nodiscard]] constexpr bool intersects(MachinePassChanges Other) const noexcept {
+ return (Bits & Other.Bits) != 0;
+ }
+
+ [[nodiscard]] constexpr bool empty() const noexcept {
+ return Bits == 0;
+ }
+
+ [[nodiscard]] constexpr std::uint32_t rawValue() const noexcept {
+ return Bits;
+ }
+
+ friend constexpr bool operator==(MachinePassChanges Left,
+ MachinePassChanges Right) noexcept = default;
+
+private:
+ [[nodiscard]] static constexpr std::uint32_t rawMask() noexcept {
+ return (1U << 9U) - 1U;
+ }
+
+ std::uint32_t Bits = 0;
+};
+
+template <>
+struct AnalysisManagerInstrumentation<MachineFunction, MachinePassInstrumentation> final {
+ static void beforeAnalysis(MachinePassInstrumentation *Instrumentation, std::string_view Name,
+ const MachineFunction &Function);
+ static void afterAnalysis(MachinePassInstrumentation *Instrumentation, std::string_view Name,
+ const MachineFunction &Function, bool CacheHit,
+ std::uint64_t Nanoseconds);
+ static void analysisFailure(MachinePassInstrumentation *Instrumentation, std::string_view Name,
+ const MachineFunction &Function, const Error &Failure,
+ std::uint64_t Nanoseconds);
+ [[nodiscard]] static Expected<bool> requestAction(MachinePassInstrumentation *Instrumentation,
+ std::string_view Pass, std::string_view Rule,
+ const MachineFunction &Function,
+ MachineInstrStableID Instruction,
+ std::uint64_t Cost);
+ [[nodiscard]] static Expected<bool> requestAction(MachinePassInstrumentation *Instrumentation,
+ std::string_view Pass, std::string_view Rule,
+ const MachineFunction &Function, std::nullptr_t,
+ std::uint64_t Cost);
+};
+
+template <>
+struct AnalysisManagerInstrumentation<CompilationUnit, MachinePassInstrumentation> final {
+ static void beforeAnalysis(MachinePassInstrumentation *Instrumentation, std::string_view Name,
+ const CompilationUnit &Unit);
+ static void afterAnalysis(MachinePassInstrumentation *Instrumentation, std::string_view Name,
+ const CompilationUnit &Unit, bool CacheHit, std::uint64_t Nanoseconds);
+ static void analysisFailure(MachinePassInstrumentation *Instrumentation, std::string_view Name,
+ const CompilationUnit &Unit, const Error &Failure,
+ std::uint64_t Nanoseconds);
+};
+
+using MachineAnalysisRegistration = AnalysisRegistration<MachinePassChanges>;
+using CompilationUnitAnalysisRegistration = AnalysisRegistration<MachinePassChanges>;
+
+using MachineFunctionAnalysisManager =
+ AnalysisManager<MachineFunction, MachineAnalysisRegistration, MachinePassChanges,
+ MachinePassInstrumentation>;
+using CompilationUnitAnalysisManager =
+ AnalysisManager<CompilationUnit, CompilationUnitAnalysisRegistration, MachinePassChanges,
+ MachinePassInstrumentation>;
+
+[[nodiscard]] Expected<void>
+registerStage8MachineAnalyses(MachineFunctionAnalysisManager &Analyses);
+[[nodiscard]] Expected<void>
+registerStage11MachineAnalyses(MachineFunctionAnalysisManager &Analyses);
+
+} // namespace rcc
+
+#endif // RCC_CODEGEN_MACHINEFUNCTIONANALYSISMANAGER_H
diff --git a/backend/include/rcc/CodeGen/MachineLICM.h b/backend/include/rcc/CodeGen/MachineLICM.h
index 66b7ef8..5efaf20 100644
--- a/backend/include/rcc/CodeGen/MachineLICM.h
+++ b/backend/include/rcc/CodeGen/MachineLICM.h
@@ -3,7 +3,7 @@
#ifndef RCC_CODEGEN_MACHINELICM_H
#define RCC_CODEGEN_MACHINELICM_H
-#include "rcc/CodeGen/MachinePass.h"
+#include "rcc/CodeGen/MachinePassManager.h"
#include <cstddef>
#include <cstdint>
@@ -29,12 +29,12 @@ public:
[[nodiscard]] const MachinePassContract &contract() const noexcept override;
[[nodiscard]] Expected<MachinePassResult> run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &Analyses) override;
+ MachineFunctionAnalysisManager &Analyses) override;
private:
- [[nodiscard]] Expected<MachinePassResult> runImplementation(MachineFunction &Function,
- const TargetDescription &Target,
- MachineAnalysisManager &Analyses);
+ [[nodiscard]] Expected<MachinePassResult>
+ runImplementation(MachineFunction &Function, const TargetDescription &Target,
+ MachineFunctionAnalysisManager &Analyses);
MachineCodeMotionStage Stage = MachineCodeMotionStage::SelectedSSA;
MachineLICMOptions Options;
diff --git a/backend/include/rcc/CodeGen/MachineMemoryFolding.h b/backend/include/rcc/CodeGen/MachineMemoryFolding.h
index 9a5b47a..9f415d7 100644
--- a/backend/include/rcc/CodeGen/MachineMemoryFolding.h
+++ b/backend/include/rcc/CodeGen/MachineMemoryFolding.h
@@ -3,7 +3,7 @@
#ifndef RCC_CODEGEN_MACHINEMEMORYFOLDING_H
#define RCC_CODEGEN_MACHINEMEMORYFOLDING_H
-#include "rcc/CodeGen/MachinePass.h"
+#include "rcc/CodeGen/MachinePassManager.h"
#include <cstddef>
@@ -24,7 +24,7 @@ public:
[[nodiscard]] const MachinePassContract &contract() const noexcept override;
[[nodiscard]] Expected<MachinePassResult> run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &Analyses) override;
+ MachineFunctionAnalysisManager &Analyses) override;
private:
[[nodiscard]] Expected<MachinePassResult>
diff --git a/backend/include/rcc/CodeGen/MachineOptimizationPipeline.h b/backend/include/rcc/CodeGen/MachineOptimizationPipeline.h
index 10bcbc6..51b4ed2 100644
--- a/backend/include/rcc/CodeGen/MachineOptimizationPipeline.h
+++ b/backend/include/rcc/CodeGen/MachineOptimizationPipeline.h
@@ -3,7 +3,7 @@
#ifndef RCC_CODEGEN_MACHINEOPTIMIZATIONPIPELINE_H
#define RCC_CODEGEN_MACHINEOPTIMIZATIONPIPELINE_H
-#include "rcc/CodeGen/MachinePass.h"
+#include "rcc/CodeGen/MachinePassManager.h"
namespace rcc {
@@ -23,17 +23,18 @@ struct MachineOptimizationPipelineTargetInfo final {
const TargetSchedulingModel &SchedulingModel;
};
-[[nodiscard]] Expected<void> registerMachineOptimizationAnalyses(MachineAnalysisManager &Analyses);
+[[nodiscard]] Expected<void>
+registerMachineOptimizationAnalyses(MachineFunctionAnalysisManager &Analyses);
[[nodiscard]] Expected<void>
-addSelectedSSAOptimizationPipeline(MachinePassManager &Pipeline,
+addSelectedSSAOptimizationPipeline(MachineFunctionPassManager &Pipeline,
const MachineOptimizationPipelineTargetInfo &TargetInfo);
[[nodiscard]] Expected<void> addPreRegisterAllocationOptimizationPipeline(
- MachinePassManager &Pipeline, const MachineOptimizationPipelineTargetInfo &TargetInfo);
+ MachineFunctionPassManager &Pipeline, const MachineOptimizationPipelineTargetInfo &TargetInfo);
[[nodiscard]] Expected<void>
-addPostRegisterAllocationPipeline(MachinePassManager &Pipeline,
+addPostRegisterAllocationPipeline(MachineFunctionPassManager &Pipeline,
const MachineOptimizationPipelineTargetInfo &TargetInfo);
} // namespace rcc
diff --git a/backend/include/rcc/CodeGen/MachinePass.h b/backend/include/rcc/CodeGen/MachinePass.h
deleted file mode 100644
index ee67924..0000000
--- a/backend/include/rcc/CodeGen/MachinePass.h
+++ /dev/null
@@ -1,720 +0,0 @@
-// SPDX-License-Identifier: GPL-3.0-or-later
-
-#ifndef RCC_CODEGEN_MACHINEPASS_H
-#define RCC_CODEGEN_MACHINEPASS_H
-
-#include "rcc/CodeGen/InstructionDescriptor.h"
-#include "rcc/CodeGen/MachineFunctionProperties.h"
-#include "rcc/CodeGen/StableID.h"
-#include "rcc/Support/Error.h"
-
-#include <concepts>
-#include <cstddef>
-#include <cstdint>
-#include <functional>
-#include <initializer_list>
-#include <memory>
-#include <mutex>
-#include <optional>
-#include <span>
-#include <string>
-#include <string_view>
-#include <unordered_map>
-#include <unordered_set>
-#include <utility>
-#include <vector>
-
-namespace rcc {
-
-class CompilationUnit;
-class MachineFunction;
-class MachineVerifier;
-class TargetDescription;
-
-using AnalysisID = const void *;
-
-enum class MachinePassChange : std::uint32_t {
- None = 0,
- Instructions = 1U << 0U,
- Operands = 1U << 1U,
- Registers = 1U << 2U,
- CFG = 1U << 3U,
- BlockLayout = 1U << 4U,
- Frame = 1U << 5U,
- ConstantPool = 1U << 6U,
- JumpTable = 1U << 7U,
- TargetState = 1U << 8U,
-};
-
-class MachinePassChanges final {
-public:
- constexpr MachinePassChanges() noexcept = default;
- constexpr MachinePassChanges(std::initializer_list<MachinePassChange> Changes) noexcept {
- for (const MachinePassChange Change : Changes)
- add(Change);
- }
-
- [[nodiscard]] static constexpr MachinePassChanges all() noexcept {
- return fromRaw((1U << 9U) - 1U);
- }
-
- [[nodiscard]] static constexpr MachinePassChanges fromRaw(std::uint32_t Bits) noexcept {
- MachinePassChanges Result;
- Result.Bits = Bits & rawMask();
- return Result;
- }
-
- constexpr void add(MachinePassChange Change) noexcept {
- Bits |= static_cast<std::uint32_t>(Change);
- }
-
- [[nodiscard]] constexpr bool has(MachinePassChange Change) const noexcept {
- return (Bits & static_cast<std::uint32_t>(Change)) != 0;
- }
-
- [[nodiscard]] constexpr bool contains(MachinePassChanges Other) const noexcept {
- return (Bits & Other.Bits) == Other.Bits;
- }
-
- [[nodiscard]] constexpr bool intersects(MachinePassChanges Other) const noexcept {
- return (Bits & Other.Bits) != 0;
- }
-
- [[nodiscard]] constexpr bool empty() const noexcept {
- return Bits == 0;
- }
-
- [[nodiscard]] constexpr std::uint32_t rawValue() const noexcept {
- return Bits;
- }
-
- friend constexpr bool operator==(MachinePassChanges Left,
- MachinePassChanges Right) noexcept = default;
-
-private:
- [[nodiscard]] static constexpr std::uint32_t rawMask() noexcept {
- return (1U << 9U) - 1U;
- }
-
- std::uint32_t Bits = 0;
-};
-
-class PreservedAnalyses final {
-public:
- [[nodiscard]] static PreservedAnalyses all() noexcept {
- PreservedAnalyses Result;
- Result.PreserveAll = true;
- return Result;
- }
-
- [[nodiscard]] static PreservedAnalyses none() noexcept {
- return {};
- }
-
- void preserve(AnalysisID ID) {
- if (ID != nullptr)
- Preserved.insert(ID);
- }
-
- template <typename AnalysisT> void preserve() {
- preserve(analysisID<AnalysisT>());
- }
-
- [[nodiscard]] bool preserves(AnalysisID ID) const noexcept {
- return PreserveAll || (ID != nullptr && Preserved.contains(ID));
- }
-
- [[nodiscard]] bool preservesAll() const noexcept {
- return PreserveAll;
- }
-
- template <typename AnalysisT> [[nodiscard]] static AnalysisID analysisID() noexcept {
- static const std::uint8_t Token = 0;
- return &Token;
- }
-
-private:
- bool PreserveAll = false;
- std::unordered_set<AnalysisID> Preserved;
-};
-
-enum class PassThreadSafety : std::uint8_t {
- NotThreadSafe,
- ThreadSafe,
-};
-
-struct PassParameter final {
- std::string Name;
- std::string Description;
- std::optional<std::string> DefaultValue;
- bool Required = false;
-};
-
-struct MachinePassRegistrationMetadata {
- std::vector<PassParameter> Parameters;
- PassThreadSafety ThreadSafety = PassThreadSafety::NotThreadSafe;
- MachinePassChanges DeclaredChanges = MachinePassChanges::all();
-};
-
-struct MachinePassContract final : MachinePassRegistrationMetadata {
- std::string Name;
- MachineFunctionProperties Requires;
- MachineFunctionProperties Sets;
- MachineFunctionProperties Clears;
- std::vector<AnalysisID> RequiredAnalyses;
- std::optional<PipelineStage> VerificationStage;
-};
-
-struct MachinePassResult final {
- bool Changed = false;
- MachinePassChanges Changes;
- PreservedAnalyses Preserved = PreservedAnalyses::none();
-};
-
-struct CompilationUnitPassContract final {
- std::string Name;
- std::vector<AnalysisID> RequiredAnalyses;
- std::vector<PassParameter> Parameters;
- MachinePassChanges DeclaredChanges = MachinePassChanges::all();
-};
-
-struct CompilationUnitPassResult final {
- bool Changed = false;
- MachinePassChanges Changes;
- PreservedAnalyses PreservedUnitAnalyses = PreservedAnalyses::none();
- PreservedAnalyses PreservedFunctionAnalyses = PreservedAnalyses::none();
-};
-
-struct MachineAnalysisRegistration final {
- AnalysisID ID = nullptr;
- std::string Name;
- std::vector<AnalysisID> Dependencies;
- MachinePassChanges InvalidatedBy = MachinePassChanges::all();
- PassThreadSafety ThreadSafety = PassThreadSafety::NotThreadSafe;
-};
-
-struct CompilationUnitAnalysisRegistration final {
- AnalysisID ID = nullptr;
- std::string Name;
- std::vector<AnalysisID> Dependencies;
- MachinePassChanges InvalidatedBy = MachinePassChanges::all();
-};
-
-class MachinePassInstrumentation;
-
-class MachineAnalysisManager final {
-public:
- MachineAnalysisManager() = default;
- MachineAnalysisManager(const MachineAnalysisManager &) = delete;
- MachineAnalysisManager &operator=(const MachineAnalysisManager &) = delete;
- MachineAnalysisManager(MachineAnalysisManager &&) = delete;
- MachineAnalysisManager &operator=(MachineAnalysisManager &&) = delete;
- ~MachineAnalysisManager() = default;
-
- template <typename AnalysisT> [[nodiscard]] static AnalysisID id() noexcept {
- return PreservedAnalyses::analysisID<AnalysisT>();
- }
-
- template <typename AnalysisT>
- [[nodiscard]] Expected<void> registerAnalysis(MachineAnalysisRegistration Registration = {}) {
- using ResultT = typename AnalysisT::Result;
- if (Registration.ID == nullptr)
- Registration.ID = id<AnalysisT>();
- if (Registration.Name.empty()) {
- if constexpr (requires {
- { AnalysisT::name() } -> std::convertible_to<std::string_view>;
- }) {
- Registration.Name = std::string(AnalysisT::name());
- } else {
- Registration.Name = "unnamed-machine-analysis";
- }
- }
-
- ErasedRunner Runner = [](MachineFunction &Function, const TargetDescription &Target,
- MachineAnalysisManager &Manager) -> Expected<std::shared_ptr<void>> {
- auto Computed = AnalysisT::run(Function, Target, Manager);
- if (!Computed)
- return std::unexpected(Computed.error());
- return std::shared_ptr<void>(new ResultT(std::move(*Computed)),
- [](void *Value) { delete static_cast<ResultT *>(Value); });
- };
- ErasedInvalidator Invalidator = [](void *Value, const MachineFunction &Function,
- const PreservedAnalyses &Preserved) -> bool {
- if constexpr (requires(ResultT &Result, const MachineFunction &InputFunction,
- const PreservedAnalyses &Analyses) {
- { Result.invalidate(InputFunction, Analyses) } -> std::convertible_to<bool>;
- }) {
- return static_cast<ResultT *>(Value)->invalidate(Function, Preserved);
- }
- return true;
- };
- return registerAnalysisImpl(std::move(Registration), std::move(Runner), std::move(Invalidator));
- }
-
- template <typename AnalysisT>
- [[nodiscard]] Expected<typename AnalysisT::Result *> getResult(MachineFunction &Function,
- const TargetDescription &Target) {
- const AnalysisID Key = id<AnalysisT>();
- if (!isRegistered(Key)) {
- auto Registered = registerAnalysis<AnalysisT>();
- if (!Registered)
- return std::unexpected(Registered.error());
- }
- auto Result = getResultImpl(Key, Function, Target);
- if (!Result)
- return std::unexpected(Result.error());
- return static_cast<typename AnalysisT::Result *>(*Result);
- }
-
- void invalidate(MachineFunction &Function, const PreservedAnalyses &Preserved,
- MachinePassChanges Changes) noexcept;
- void invalidate(MachineFunction &Function, const PreservedAnalyses &Preserved) noexcept {
- invalidate(Function, Preserved, MachinePassChanges::all());
- }
- [[nodiscard]] bool hasCached(const MachineFunction &Function, AnalysisID ID) const noexcept;
- [[nodiscard]] bool isRegistered(AnalysisID ID) const noexcept;
- [[nodiscard]] std::size_t cachedResultCount(const MachineFunction &Function) const noexcept;
- void clear(MachineFunction &Function) noexcept;
- void clearAll() noexcept;
-
- [[nodiscard]] Expected<std::unique_ptr<MachineAnalysisManager>> forkEmpty() const;
- [[nodiscard]] Expected<bool>
- requestAction(std::string_view Action, const MachineFunction &Function, std::uint64_t Cost = 1);
- [[nodiscard]] Expected<bool> requestAction(std::string_view Rule, const MachineFunction &Function,
- MachineInstrStableID Instruction,
- std::uint64_t Cost = 1);
-
-private:
- using ErasedRunner = std::function<Expected<std::shared_ptr<void>>(
- MachineFunction &, const TargetDescription &, MachineAnalysisManager &)>;
- using ErasedInvalidator =
- std::function<bool(void *, const MachineFunction &, const PreservedAnalyses &)>;
-
- struct RegisteredAnalysis final {
- MachineAnalysisRegistration Info;
- ErasedRunner Runner;
- ErasedInvalidator Invalidator;
- };
-
- struct CacheEntry final {
- std::shared_ptr<void> Value;
- AnalysisID ID = nullptr;
- };
-
- [[nodiscard]] Expected<void> registerAnalysisImpl(MachineAnalysisRegistration Registration,
- ErasedRunner Runner,
- ErasedInvalidator Invalidator);
- [[nodiscard]] Expected<void *> getResultImpl(AnalysisID ID, MachineFunction &Function,
- const TargetDescription &Target);
- [[nodiscard]] Expected<void> materializeDependencies(const RegisteredAnalysis &Registration,
- MachineFunction &Function,
- const TargetDescription &Target);
- [[nodiscard]] Expected<void>
- validateParallelRequirements(std::span<const AnalysisID> RequiredAnalyses) const;
- void setInstrumentation(MachinePassInstrumentation *NewInstrumentation) noexcept {
- Instrumentation = NewInstrumentation;
- }
-
- std::unordered_map<AnalysisID, RegisteredAnalysis> Registry;
- std::unordered_map<MachineFunction *, std::unordered_map<AnalysisID, CacheEntry>> Cache;
- std::unordered_map<MachineFunction *, std::vector<AnalysisID>> ActiveComputations;
- MachinePassInstrumentation *Instrumentation = nullptr;
- std::string ActivePass;
-
- friend class MachinePassManager;
- friend class CompilationUnitPassManager;
- friend Expected<void> registerStage8MachineAnalyses(MachineAnalysisManager &Analyses);
- friend Expected<void> registerStage11MachineAnalyses(MachineAnalysisManager &Analyses);
-};
-
-class CompilationUnitAnalysisManager final {
-public:
- CompilationUnitAnalysisManager() = default;
- CompilationUnitAnalysisManager(const CompilationUnitAnalysisManager &) = delete;
- CompilationUnitAnalysisManager &operator=(const CompilationUnitAnalysisManager &) = delete;
- CompilationUnitAnalysisManager(CompilationUnitAnalysisManager &&) = delete;
- CompilationUnitAnalysisManager &operator=(CompilationUnitAnalysisManager &&) = delete;
- ~CompilationUnitAnalysisManager() = default;
-
- template <typename AnalysisT> [[nodiscard]] static AnalysisID id() noexcept {
- return PreservedAnalyses::analysisID<AnalysisT>();
- }
-
- template <typename AnalysisT>
- [[nodiscard]] Expected<void>
- registerAnalysis(CompilationUnitAnalysisRegistration Registration = {}) {
- using ResultT = typename AnalysisT::Result;
- if (Registration.ID == nullptr)
- Registration.ID = id<AnalysisT>();
- if (Registration.Name.empty()) {
- if constexpr (requires {
- { AnalysisT::name() } -> std::convertible_to<std::string_view>;
- }) {
- Registration.Name = std::string(AnalysisT::name());
- } else {
- Registration.Name = "unnamed-compilation-unit-analysis";
- }
- }
-
- ErasedRunner Runner =
- [](CompilationUnit &Unit, const TargetDescription &Target,
- CompilationUnitAnalysisManager &Manager) -> Expected<std::shared_ptr<void>> {
- auto Computed = AnalysisT::run(Unit, Target, Manager);
- if (!Computed)
- return std::unexpected(Computed.error());
- return std::shared_ptr<void>(new ResultT(std::move(*Computed)),
- [](void *Value) { delete static_cast<ResultT *>(Value); });
- };
- ErasedInvalidator Invalidator = [](void *Value, const CompilationUnit &Unit,
- const PreservedAnalyses &Preserved) -> bool {
- if constexpr (requires(ResultT &Result, const CompilationUnit &InputUnit,
- const PreservedAnalyses &Analyses) {
- { Result.invalidate(InputUnit, Analyses) } -> std::convertible_to<bool>;
- }) {
- return static_cast<ResultT *>(Value)->invalidate(Unit, Preserved);
- }
- return true;
- };
- return registerAnalysisImpl(std::move(Registration), std::move(Runner), std::move(Invalidator));
- }
-
- template <typename AnalysisT>
- [[nodiscard]] Expected<typename AnalysisT::Result *> getResult(CompilationUnit &Unit,
- const TargetDescription &Target) {
- const AnalysisID Key = id<AnalysisT>();
- if (!isRegistered(Key)) {
- auto Registered = registerAnalysis<AnalysisT>();
- if (!Registered)
- return std::unexpected(Registered.error());
- }
- auto Result = getResultImpl(Key, Unit, Target);
- if (!Result)
- return std::unexpected(Result.error());
- return static_cast<typename AnalysisT::Result *>(*Result);
- }
-
- void invalidate(CompilationUnit &Unit, const PreservedAnalyses &Preserved,
- MachinePassChanges Changes) noexcept;
- [[nodiscard]] bool hasCached(const CompilationUnit &Unit, AnalysisID ID) const noexcept;
- [[nodiscard]] bool isRegistered(AnalysisID ID) const noexcept;
- void clear(CompilationUnit &Unit) noexcept;
- void clearAll() noexcept;
-
-private:
- using ErasedRunner = std::function<Expected<std::shared_ptr<void>>(
- CompilationUnit &, const TargetDescription &, CompilationUnitAnalysisManager &)>;
- using ErasedInvalidator =
- std::function<bool(void *, const CompilationUnit &, const PreservedAnalyses &)>;
-
- struct RegisteredAnalysis final {
- CompilationUnitAnalysisRegistration Info;
- ErasedRunner Runner;
- ErasedInvalidator Invalidator;
- };
-
- struct CacheEntry final {
- std::shared_ptr<void> Value;
- AnalysisID ID = nullptr;
- };
-
- [[nodiscard]] Expected<void>
- registerAnalysisImpl(CompilationUnitAnalysisRegistration Registration, ErasedRunner Runner,
- ErasedInvalidator Invalidator);
- [[nodiscard]] Expected<void *> getResultImpl(AnalysisID ID, CompilationUnit &Unit,
- const TargetDescription &Target);
- [[nodiscard]] Expected<void> materializeDependencies(const RegisteredAnalysis &Registration,
- CompilationUnit &Unit,
- const TargetDescription &Target);
- void setInstrumentation(MachinePassInstrumentation *NewInstrumentation) noexcept {
- Instrumentation = NewInstrumentation;
- }
-
- std::unordered_map<AnalysisID, RegisteredAnalysis> Registry;
- std::unordered_map<CompilationUnit *, std::unordered_map<AnalysisID, CacheEntry>> Cache;
- std::unordered_map<CompilationUnit *, std::vector<AnalysisID>> ActiveComputations;
- MachinePassInstrumentation *Instrumentation = nullptr;
-
- friend class CompilationUnitPassManager;
-};
-
-class MachineFunctionPass {
-public:
- MachineFunctionPass() = default;
- MachineFunctionPass(const MachineFunctionPass &) = delete;
- MachineFunctionPass &operator=(const MachineFunctionPass &) = delete;
- virtual ~MachineFunctionPass() = default;
-
- [[nodiscard]] virtual const MachinePassContract &contract() const noexcept = 0;
- [[nodiscard]] virtual Expected<MachinePassResult> run(MachineFunction &Function,
- const TargetDescription &Target,
- MachineAnalysisManager &Analyses) = 0;
-};
-
-class CompilationUnitPass {
-public:
- CompilationUnitPass() = default;
- CompilationUnitPass(const CompilationUnitPass &) = delete;
- CompilationUnitPass &operator=(const CompilationUnitPass &) = delete;
- virtual ~CompilationUnitPass() = default;
-
- [[nodiscard]] virtual const CompilationUnitPassContract &contract() const noexcept = 0;
- [[nodiscard]] virtual Expected<CompilationUnitPassResult>
- run(CompilationUnit &Unit, const TargetDescription &Target,
- CompilationUnitAnalysisManager &UnitAnalyses, MachineAnalysisManager &FunctionAnalyses) = 0;
-};
-
-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 MachineActionReplay final {
-public:
- explicit MachineActionReplay(MachineAnalysisManager &Analyses) noexcept : Analyses(&Analyses) {}
- MachineActionReplay(
- MachineAnalysisManager &Analyses,
- const std::unordered_map<MachineInstrStableID, MachineInstrStableID> &SourceToClone)
- : Analyses(&Analyses) {
- for (const auto &[Source, Clone] : SourceToClone)
- RecordingInstructionIDs.try_emplace(Clone, Source);
- }
-
- [[nodiscard]] Expected<bool> request(std::string_view Rule, const MachineFunction &Function,
- MachineInstrStableID Instruction = {},
- std::uint64_t Cost = 1);
- void beginReplay() noexcept;
- [[nodiscard]] Expected<void> finishReplay() const;
-
-private:
- struct Decision final {
- std::string Rule;
- MachineFunctionStableID Function;
- MachineInstrStableID Instruction;
- std::uint64_t Cost = 0;
- bool Accepted = false;
- };
-
- MachineAnalysisManager *Analyses = nullptr;
- std::unordered_map<MachineInstrStableID, MachineInstrStableID> RecordingInstructionIDs;
- std::vector<Decision> Decisions;
- std::size_t NextDecision = 0;
- bool IsReplaying = false;
-};
-
-class MachinePassInstrumentation 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 AfterAnalysisCallback =
- std::function<void(std::string_view, const MachineFunction &, 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;
- void clearStatistics();
-
-private:
- struct BufferedEvents final {
- const TargetDescription *Target = nullptr;
- std::vector<std::function<void()>> Events;
- };
-
- [[nodiscard]] bool bufferFunctionEvent(const MachineFunction &Function,
- std::function<void(const MachineFunction &)> Replay) const;
- void beginBuffering(BufferedEvents &Buffer, const TargetDescription &Target) const noexcept;
- void endBuffering() const noexcept;
- void replayBufferedEvents(BufferedEvents &Buffer) const;
-
- void before(std::string_view Name, const MachineFunction &Function) const;
- void after(std::string_view Name, const MachineFunction &Function,
- const MachinePassResult &Result, std::uint64_t Nanoseconds) const;
- void failure(std::string_view Name, const MachineFunction &Function, const Error &ErrorValue,
- std::uint64_t Nanoseconds = 0) const;
- void beforeAnalysis(std::string_view Name, const MachineFunction &Function) const;
- void afterAnalysis(std::string_view Name, const MachineFunction &Function, bool CacheHit,
- std::uint64_t Nanoseconds) const;
- void analysisFailure(std::string_view Name, const MachineFunction &Function,
- const Error &ErrorValue, std::uint64_t Nanoseconds) const;
- void change(std::string_view Name, const MachineFunction &Function, MachinePassChanges Changes,
- bool FingerprintChanged) const;
- [[nodiscard]] Expected<bool> requestAction(const MachineActionID &Action,
- const MachineFunction &Function, std::uint64_t Cost);
-
- 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 beforeUnitAnalysis(std::string_view Name, const CompilationUnit &Unit) const;
- void afterUnitAnalysis(std::string_view Name, const CompilationUnit &Unit, bool CacheHit,
- std::uint64_t Nanoseconds) const;
- void unitAnalysisFailure(std::string_view Name, const CompilationUnit &Unit,
- const Error &ErrorValue, std::uint64_t Nanoseconds) const;
-
- [[nodiscard]] InstrumentationStatistic &statistic(std::string_view Name, bool IsAnalysis) const;
-
- mutable std::mutex Mutex;
- mutable std::mutex ActionMutex;
- std::vector<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;
-
- static thread_local BufferedEvents *ActiveBuffer;
-
- friend class CompilationUnitAnalysisManager;
- friend class CompilationUnitPassManager;
- friend class MachineAnalysisManager;
- friend class MachinePassManager;
-};
-
-struct MachinePassManagerOptions final {
- bool VerifyBefore = true;
- bool VerifyEach = true;
- bool DetectUnreportedChanges = false;
-};
-
-class MachinePassManager final {
-public:
- using PassList = std::vector<std::unique_ptr<MachineFunctionPass>>;
-
- explicit MachinePassManager(MachinePassManagerOptions Options = {}) : Options(Options) {}
-
- MachinePassManager(const MachinePassManager &) = delete;
- MachinePassManager &operator=(const MachinePassManager &) = delete;
-
- [[nodiscard]] Expected<void> addPass(std::unique_ptr<MachineFunctionPass> Pass);
- [[nodiscard]] Expected<void> run(MachineFunction &Function, const TargetDescription &Target,
- MachineAnalysisManager &Analyses,
- MachinePassInstrumentation *Instrumentation = nullptr) const;
- [[nodiscard]] Expected<void>
- runFunctions(CompilationUnit &Unit, const TargetDescription &Target,
- const MachineAnalysisManager &AnalysisPrototype, std::size_t ThreadCount,
- MachinePassInstrumentation *Instrumentation = nullptr) const;
-
- [[nodiscard]] std::size_t size() const noexcept {
- return Passes.size();
- }
-
- [[nodiscard]] PassList takePasses() && noexcept {
- return std::move(Passes);
- }
-
-private:
- [[nodiscard]] Expected<void> validateContract(const MachinePassContract &Contract) const;
-
- MachinePassManagerOptions Options;
- PassList Passes;
-};
-
-struct CompilationUnitPassManagerOptions final {
- bool VerifyBefore = true;
- bool VerifyEach = true;
-};
-
-class CompilationUnitPassManager final {
-public:
- explicit CompilationUnitPassManager(CompilationUnitPassManagerOptions Options = {})
- : Options(Options) {}
-
- CompilationUnitPassManager(const CompilationUnitPassManager &) = delete;
- CompilationUnitPassManager &operator=(const CompilationUnitPassManager &) = delete;
-
- [[nodiscard]] Expected<void> addPass(std::unique_ptr<CompilationUnitPass> Pass);
- [[nodiscard]] Expected<void> run(CompilationUnit &Unit, const TargetDescription &Target,
- CompilationUnitAnalysisManager &UnitAnalyses,
- MachineAnalysisManager &FunctionAnalyses,
- MachinePassInstrumentation *Instrumentation = nullptr) const;
-
-private:
- CompilationUnitPassManagerOptions Options;
- std::vector<std::unique_ptr<CompilationUnitPass>> Passes;
-};
-
-} // namespace rcc
-
-#endif // RCC_CODEGEN_MACHINEPASS_H
diff --git a/backend/include/rcc/CodeGen/MachinePassManager.h b/backend/include/rcc/CodeGen/MachinePassManager.h
new file mode 100644
index 0000000..3587395
--- /dev/null
+++ b/backend/include/rcc/CodeGen/MachinePassManager.h
@@ -0,0 +1,134 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef RCC_CODEGEN_MACHINEPASSMANAGER_H
+#define RCC_CODEGEN_MACHINEPASSMANAGER_H
+
+#include "rcc/CodeGen/InstructionDescriptor.h"
+#include "rcc/CodeGen/MachineFunctionAnalysisManager.h"
+#include "rcc/CodeGen/MachineFunctionProperties.h"
+#include "rcc/IR/PassInstrumentation.h"
+
+#include <cstddef>
+#include <memory>
+#include <optional>
+#include <string>
+#include <vector>
+
+namespace rcc {
+
+class CompilationUnit;
+class MachineFunction;
+class TargetDescription;
+
+struct MachinePassRegistrationMetadata {
+ std::vector<PassParameter> Parameters;
+ PassThreadSafety ThreadSafety = PassThreadSafety::NotThreadSafe;
+ MachinePassChanges DeclaredChanges = MachinePassChanges::all();
+};
+
+struct MachinePassContract final : MachinePassRegistrationMetadata {
+ std::string Name;
+ MachineFunctionProperties Requires;
+ MachineFunctionProperties Sets;
+ MachineFunctionProperties Clears;
+ std::vector<AnalysisID> RequiredAnalyses;
+ std::optional<PipelineStage> VerificationStage;
+};
+
+struct MachinePassResult final {
+ bool Changed = false;
+ MachinePassChanges Changes;
+ PreservedAnalyses Preserved = PreservedAnalyses::none();
+};
+
+struct CompilationUnitPassContract final {
+ std::string Name;
+ std::vector<AnalysisID> RequiredAnalyses;
+ std::vector<PassParameter> Parameters;
+ MachinePassChanges DeclaredChanges = MachinePassChanges::all();
+};
+
+struct CompilationUnitPassResult final {
+ bool Changed = false;
+ MachinePassChanges Changes;
+ PreservedAnalyses PreservedUnitAnalyses = PreservedAnalyses::none();
+ PreservedAnalyses PreservedFunctionAnalyses = PreservedAnalyses::none();
+};
+
+class MachineFunctionPass {
+public:
+ MachineFunctionPass() = default;
+ MachineFunctionPass(const MachineFunctionPass &) = delete;
+ MachineFunctionPass &operator=(const MachineFunctionPass &) = delete;
+ virtual ~MachineFunctionPass() = default;
+
+ [[nodiscard]] virtual const MachinePassContract &contract() const noexcept = 0;
+ [[nodiscard]] virtual Expected<MachinePassResult>
+ run(MachineFunction &Function, const TargetDescription &Target,
+ MachineFunctionAnalysisManager &Analyses) = 0;
+};
+
+class CompilationUnitPass {
+public:
+ CompilationUnitPass() = default;
+ CompilationUnitPass(const CompilationUnitPass &) = delete;
+ CompilationUnitPass &operator=(const CompilationUnitPass &) = delete;
+ virtual ~CompilationUnitPass() = default;
+
+ [[nodiscard]] virtual const CompilationUnitPassContract &contract() const noexcept = 0;
+ [[nodiscard]] virtual Expected<CompilationUnitPassResult>
+ run(CompilationUnit &Unit, const TargetDescription &Target,
+ CompilationUnitAnalysisManager &UnitAnalyses,
+ MachineFunctionAnalysisManager &FunctionAnalyses) = 0;
+};
+
+struct MachinePassManagerOptions final {
+ bool VerifyBefore = true;
+ bool VerifyEach = true;
+ bool DetectUnreportedChanges = false;
+};
+
+template <>
+struct PassManagerCallbacks<MachineFunction, MachineFunctionPass, MachinePassManagerOptions> final {
+ using PassList = std::vector<std::unique_ptr<MachineFunctionPass>>;
+
+ [[nodiscard]] static Expected<void> validate(const MachineFunctionPass &Pass);
+ [[nodiscard]] static Expected<void>
+ run(const PassList &Passes, const MachinePassManagerOptions &Options, MachineFunction &Function,
+ const TargetDescription &Target, MachineFunctionAnalysisManager &Analyses,
+ MachinePassInstrumentation *Instrumentation = nullptr);
+ [[nodiscard]] static Expected<void>
+ runFunctions(const PassList &Passes, const MachinePassManagerOptions &Options,
+ CompilationUnit &Unit, const TargetDescription &Target,
+ const MachineFunctionAnalysisManager &AnalysisPrototype, std::size_t ThreadCount,
+ MachinePassInstrumentation *Instrumentation = nullptr);
+};
+
+using MachineFunctionPassManager =
+ PassManager<MachineFunction, MachineFunctionPass, MachinePassManagerOptions>;
+
+struct CompilationUnitPassManagerOptions final {
+ bool VerifyBefore = true;
+ bool VerifyEach = true;
+};
+
+template <>
+struct PassManagerCallbacks<CompilationUnit, CompilationUnitPass, CompilationUnitPassManagerOptions>
+ final {
+ using PassList = std::vector<std::unique_ptr<CompilationUnitPass>>;
+
+ [[nodiscard]] static Expected<void> validate(const CompilationUnitPass &Pass);
+ [[nodiscard]] static Expected<void> run(const PassList &Passes,
+ const CompilationUnitPassManagerOptions &Options,
+ CompilationUnit &Unit, const TargetDescription &Target,
+ CompilationUnitAnalysisManager &UnitAnalyses,
+ MachineFunctionAnalysisManager &FunctionAnalyses,
+ MachinePassInstrumentation *Instrumentation = nullptr);
+};
+
+using CompilationUnitPassManager =
+ PassManager<CompilationUnit, CompilationUnitPass, CompilationUnitPassManagerOptions>;
+
+} // namespace rcc
+
+#endif // RCC_CODEGEN_MACHINEPASSMANAGER_H
diff --git a/backend/include/rcc/CodeGen/MachinePseudoExpansion.h b/backend/include/rcc/CodeGen/MachinePseudoExpansion.h
index 8c47441..7d4b309 100644
--- a/backend/include/rcc/CodeGen/MachinePseudoExpansion.h
+++ b/backend/include/rcc/CodeGen/MachinePseudoExpansion.h
@@ -3,7 +3,7 @@
#ifndef RCC_CODEGEN_MACHINEPSEUDOEXPANSION_H
#define RCC_CODEGEN_MACHINEPSEUDOEXPANSION_H
-#include "rcc/CodeGen/MachinePass.h"
+#include "rcc/CodeGen/MachinePassManager.h"
#include "rcc/CodeGen/TargetPseudoExpansion.h"
namespace rcc {
@@ -18,7 +18,7 @@ public:
[[nodiscard]] const MachinePassContract &contract() const noexcept override;
[[nodiscard]] Expected<MachinePassResult> run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &Analyses) override;
+ MachineFunctionAnalysisManager &Analyses) override;
private:
const TargetPseudoExpansionInfo *Info;
@@ -32,7 +32,7 @@ public:
[[nodiscard]] const MachinePassContract &contract() const noexcept override;
[[nodiscard]] Expected<MachinePassResult> run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &Analyses) override;
+ MachineFunctionAnalysisManager &Analyses) override;
private:
const TargetPseudoExpansionInfo *Info;
@@ -45,7 +45,7 @@ public:
[[nodiscard]] const MachinePassContract &contract() const noexcept override;
[[nodiscard]] Expected<MachinePassResult> run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &Analyses) override;
+ MachineFunctionAnalysisManager &Analyses) override;
private:
const TargetPseudoExpansionInfo *Info;
@@ -60,7 +60,7 @@ public:
[[nodiscard]] const MachinePassContract &contract() const noexcept override;
[[nodiscard]] Expected<MachinePassResult> run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &Analyses) override;
+ MachineFunctionAnalysisManager &Analyses) override;
private:
const TargetPseudoExpansionInfo *Info;
diff --git a/backend/include/rcc/CodeGen/MachineScheduler.h b/backend/include/rcc/CodeGen/MachineScheduler.h
index 2b48fe7..bfe9265 100644
--- a/backend/include/rcc/CodeGen/MachineScheduler.h
+++ b/backend/include/rcc/CodeGen/MachineScheduler.h
@@ -3,7 +3,7 @@
#ifndef RCC_CODEGEN_MACHINESCHEDULER_H
#define RCC_CODEGEN_MACHINESCHEDULER_H
-#include "rcc/CodeGen/MachinePass.h"
+#include "rcc/CodeGen/MachinePassManager.h"
#include <cstddef>
@@ -25,7 +25,7 @@ public:
[[nodiscard]] const MachinePassContract &contract() const noexcept override;
[[nodiscard]] Expected<MachinePassResult> run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &Analyses) override;
+ MachineFunctionAnalysisManager &Analyses) override;
private:
const TargetSchedulingModel *Model;
diff --git a/backend/include/rcc/CodeGen/MachineShrinkWrapping.h b/backend/include/rcc/CodeGen/MachineShrinkWrapping.h
index ec295cd..14edeb7 100644
--- a/backend/include/rcc/CodeGen/MachineShrinkWrapping.h
+++ b/backend/include/rcc/CodeGen/MachineShrinkWrapping.h
@@ -3,7 +3,7 @@
#ifndef RCC_CODEGEN_MACHINESHRINKWRAPPING_H
#define RCC_CODEGEN_MACHINESHRINKWRAPPING_H
-#include "rcc/CodeGen/MachinePass.h"
+#include "rcc/CodeGen/MachinePassManager.h"
#include <cstddef>
@@ -24,7 +24,7 @@ public:
[[nodiscard]] const MachinePassContract &contract() const noexcept override;
[[nodiscard]] Expected<MachinePassResult> run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &Analyses) override;
+ MachineFunctionAnalysisManager &Analyses) override;
private:
const TargetFrameLowering *Info;
diff --git a/backend/include/rcc/CodeGen/MachineSink.h b/backend/include/rcc/CodeGen/MachineSink.h
index 92aceba..5b47f9b 100644
--- a/backend/include/rcc/CodeGen/MachineSink.h
+++ b/backend/include/rcc/CodeGen/MachineSink.h
@@ -22,12 +22,12 @@ public:
[[nodiscard]] const MachinePassContract &contract() const noexcept override;
[[nodiscard]] Expected<MachinePassResult> run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &Analyses) override;
+ MachineFunctionAnalysisManager &Analyses) override;
private:
- [[nodiscard]] Expected<MachinePassResult> runImplementation(MachineFunction &Function,
- const TargetDescription &Target,
- MachineAnalysisManager &Analyses);
+ [[nodiscard]] Expected<MachinePassResult>
+ runImplementation(MachineFunction &Function, const TargetDescription &Target,
+ MachineFunctionAnalysisManager &Analyses);
MachineCodeMotionStage Stage = MachineCodeMotionStage::SelectedSSA;
MachineSinkOptions Options;
diff --git a/backend/include/rcc/CodeGen/MachineStackSlotColoring.h b/backend/include/rcc/CodeGen/MachineStackSlotColoring.h
index 19c1c70..9aae710 100644
--- a/backend/include/rcc/CodeGen/MachineStackSlotColoring.h
+++ b/backend/include/rcc/CodeGen/MachineStackSlotColoring.h
@@ -3,7 +3,7 @@
#ifndef RCC_CODEGEN_MACHINESTACKSLOTCOLORING_H
#define RCC_CODEGEN_MACHINESTACKSLOTCOLORING_H
-#include "rcc/CodeGen/MachinePass.h"
+#include "rcc/CodeGen/MachinePassManager.h"
#include <cstddef>
@@ -21,7 +21,7 @@ public:
[[nodiscard]] const MachinePassContract &contract() const noexcept override;
[[nodiscard]] Expected<MachinePassResult> run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &Analyses) override;
+ MachineFunctionAnalysisManager &Analyses) override;
private:
[[nodiscard]] Expected<MachinePassResult> runImplementation(MachineFunction &Function) const;
diff --git a/backend/include/rcc/CodeGen/MachineTailDuplication.h b/backend/include/rcc/CodeGen/MachineTailDuplication.h
index 1c21bdf..f52f638 100644
--- a/backend/include/rcc/CodeGen/MachineTailDuplication.h
+++ b/backend/include/rcc/CodeGen/MachineTailDuplication.h
@@ -3,7 +3,7 @@
#ifndef RCC_CODEGEN_MACHINETAILDUPLICATION_H
#define RCC_CODEGEN_MACHINETAILDUPLICATION_H
-#include "rcc/CodeGen/MachinePass.h"
+#include "rcc/CodeGen/MachinePassManager.h"
#include <cstddef>
@@ -25,7 +25,7 @@ public:
[[nodiscard]] const MachinePassContract &contract() const noexcept override;
[[nodiscard]] Expected<MachinePassResult> run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &Analyses) override;
+ MachineFunctionAnalysisManager &Analyses) override;
private:
[[nodiscard]] Expected<MachinePassResult>
diff --git a/backend/include/rcc/CodeGen/MachineTailMerge.h b/backend/include/rcc/CodeGen/MachineTailMerge.h
index 7237d58..0b9938e 100644
--- a/backend/include/rcc/CodeGen/MachineTailMerge.h
+++ b/backend/include/rcc/CodeGen/MachineTailMerge.h
@@ -3,7 +3,7 @@
#ifndef RCC_CODEGEN_MACHINETAILMERGE_H
#define RCC_CODEGEN_MACHINETAILMERGE_H
-#include "rcc/CodeGen/MachinePass.h"
+#include "rcc/CodeGen/MachinePassManager.h"
#include <cstddef>
@@ -24,7 +24,7 @@ public:
[[nodiscard]] const MachinePassContract &contract() const noexcept override;
[[nodiscard]] Expected<MachinePassResult> run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &Analyses) override;
+ MachineFunctionAnalysisManager &Analyses) override;
private:
[[nodiscard]] Expected<MachinePassResult>
diff --git a/backend/include/rcc/CodeGen/PHIElimination.h b/backend/include/rcc/CodeGen/PHIElimination.h
index 3d69152..1443303 100644
--- a/backend/include/rcc/CodeGen/PHIElimination.h
+++ b/backend/include/rcc/CodeGen/PHIElimination.h
@@ -3,7 +3,7 @@
#ifndef RCC_CODEGEN_PHIELIMINATION_H
#define RCC_CODEGEN_PHIELIMINATION_H
-#include "rcc/CodeGen/MachinePass.h"
+#include "rcc/CodeGen/MachinePassManager.h"
namespace rcc {
@@ -16,7 +16,7 @@ public:
[[nodiscard]] const MachinePassContract &contract() const noexcept override;
[[nodiscard]] Expected<MachinePassResult> run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &Analyses) override;
+ MachineFunctionAnalysisManager &Analyses) override;
private:
[[nodiscard]] Expected<MachinePassResult> runImplementation(MachineFunction &Function,
diff --git a/backend/include/rcc/CodeGen/PostRAScheduler.h b/backend/include/rcc/CodeGen/PostRAScheduler.h
index 13b08df..3254d1e 100644
--- a/backend/include/rcc/CodeGen/PostRAScheduler.h
+++ b/backend/include/rcc/CodeGen/PostRAScheduler.h
@@ -3,7 +3,7 @@
#ifndef RCC_CODEGEN_POSTRASCHEDULER_H
#define RCC_CODEGEN_POSTRASCHEDULER_H
-#include "rcc/CodeGen/MachinePass.h"
+#include "rcc/CodeGen/MachinePassManager.h"
#include "rcc/CodeGen/MachineScheduler.h"
namespace rcc {
@@ -19,7 +19,7 @@ public:
[[nodiscard]] const MachinePassContract &contract() const noexcept override;
[[nodiscard]] Expected<MachinePassResult> run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &Analyses) override;
+ MachineFunctionAnalysisManager &Analyses) override;
private:
const TargetSchedulingModel *Model;
diff --git a/backend/include/rcc/CodeGen/PrologueEpilogueInsertion.h b/backend/include/rcc/CodeGen/PrologueEpilogueInsertion.h
index b94715a..a5d0028 100644
--- a/backend/include/rcc/CodeGen/PrologueEpilogueInsertion.h
+++ b/backend/include/rcc/CodeGen/PrologueEpilogueInsertion.h
@@ -3,7 +3,7 @@
#ifndef RCC_CODEGEN_PROLOGUEEPILOGUEINSERTION_H
#define RCC_CODEGEN_PROLOGUEEPILOGUEINSERTION_H
-#include "rcc/CodeGen/MachinePass.h"
+#include "rcc/CodeGen/MachinePassManager.h"
namespace rcc {
@@ -16,7 +16,7 @@ public:
[[nodiscard]] const MachinePassContract &contract() const noexcept override;
[[nodiscard]] Expected<MachinePassResult> run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &Analyses) override;
+ MachineFunctionAnalysisManager &Analyses) override;
private:
[[nodiscard]] Expected<MachinePassResult>
diff --git a/backend/include/rcc/CodeGen/RegAllocCommon.h b/backend/include/rcc/CodeGen/RegAllocCommon.h
index 0df9799..ac3aa56 100644
--- a/backend/include/rcc/CodeGen/RegAllocCommon.h
+++ b/backend/include/rcc/CodeGen/RegAllocCommon.h
@@ -3,7 +3,7 @@
#ifndef RCC_CODEGEN_REGALLOCCOMMON_H
#define RCC_CODEGEN_REGALLOCCOMMON_H
-#include "rcc/CodeGen/MachinePass.h"
+#include "rcc/CodeGen/MachinePassManager.h"
#include <memory>
diff --git a/backend/include/rcc/CodeGen/RegAllocFast.h b/backend/include/rcc/CodeGen/RegAllocFast.h
index 84cf30c..6ee2881 100644
--- a/backend/include/rcc/CodeGen/RegAllocFast.h
+++ b/backend/include/rcc/CodeGen/RegAllocFast.h
@@ -3,7 +3,7 @@
#ifndef RCC_CODEGEN_REGALLOCFAST_H
#define RCC_CODEGEN_REGALLOCFAST_H
-#include "rcc/CodeGen/MachinePass.h"
+#include "rcc/CodeGen/MachinePassManager.h"
#include "rcc/CodeGen/TargetRegisterAllocationInfo.h"
namespace rcc {
@@ -15,7 +15,7 @@ public:
[[nodiscard]] const MachinePassContract &contract() const noexcept override;
[[nodiscard]] Expected<MachinePassResult> run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &Analyses) override;
+ MachineFunctionAnalysisManager &Analyses) override;
private:
const TargetRegisterAllocationInfo *Info;
diff --git a/backend/include/rcc/CodeGen/RegAllocPBQP.h b/backend/include/rcc/CodeGen/RegAllocPBQP.h
index 368cbee..0ae0088 100644
--- a/backend/include/rcc/CodeGen/RegAllocPBQP.h
+++ b/backend/include/rcc/CodeGen/RegAllocPBQP.h
@@ -17,7 +17,7 @@ public:
[[nodiscard]] const MachinePassContract &contract() const noexcept override;
[[nodiscard]] Expected<MachinePassResult> run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &Analyses) override;
+ MachineFunctionAnalysisManager &Analyses) override;
private:
const TargetRegisterAllocationInfo *Info;
diff --git a/backend/include/rcc/CodeGen/SlotIndexes.h b/backend/include/rcc/CodeGen/SlotIndexes.h
index 1767596..423cc64 100644
--- a/backend/include/rcc/CodeGen/SlotIndexes.h
+++ b/backend/include/rcc/CodeGen/SlotIndexes.h
@@ -4,7 +4,7 @@
#define RCC_CODEGEN_SLOTINDEXES_H
#include "rcc/CodeGen/MachineIRTypes.h"
-#include "rcc/CodeGen/MachinePass.h"
+#include "rcc/CodeGen/MachinePassManager.h"
#include "rcc/CodeGen/StableID.h"
#include "rcc/Support/Error.h"
@@ -115,8 +115,9 @@ public:
return "SlotIndexes";
}
- [[nodiscard]] static Expected<Result>
- run(MachineFunction &Function, const TargetDescription &Target, MachineAnalysisManager &Analyses);
+ [[nodiscard]] static Expected<Result> run(MachineFunction &Function,
+ const TargetDescription &Target,
+ MachineFunctionAnalysisManager &Analyses);
};
} // namespace rcc
diff --git a/backend/include/rcc/CodeGen/TwoAddressInstructionPass.h b/backend/include/rcc/CodeGen/TwoAddressInstructionPass.h
index 696b46c..3c9e9dc 100644
--- a/backend/include/rcc/CodeGen/TwoAddressInstructionPass.h
+++ b/backend/include/rcc/CodeGen/TwoAddressInstructionPass.h
@@ -3,7 +3,7 @@
#ifndef RCC_CODEGEN_TWOADDRESSINSTRUCTIONPASS_H
#define RCC_CODEGEN_TWOADDRESSINSTRUCTIONPASS_H
-#include "rcc/CodeGen/MachinePass.h"
+#include "rcc/CodeGen/MachinePassManager.h"
namespace rcc {
@@ -16,7 +16,7 @@ public:
[[nodiscard]] const MachinePassContract &contract() const noexcept override;
[[nodiscard]] Expected<MachinePassResult> run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &Analyses) override;
+ MachineFunctionAnalysisManager &Analyses) override;
private:
[[nodiscard]] Expected<MachinePassResult> runImplementation(MachineFunction &Function,
diff --git a/backend/include/rcc/CodeGen/VirtRegMap.h b/backend/include/rcc/CodeGen/VirtRegMap.h
index f37af84..30ef450 100644
--- a/backend/include/rcc/CodeGen/VirtRegMap.h
+++ b/backend/include/rcc/CodeGen/VirtRegMap.h
@@ -4,7 +4,7 @@
#define RCC_CODEGEN_VIRTREGMAP_H
#include "rcc/CodeGen/MachineFrameInfo.h"
-#include "rcc/CodeGen/MachinePass.h"
+#include "rcc/CodeGen/MachinePassManager.h"
#include "rcc/CodeGen/TargetRegisterInfo.h"
#include <cstdint>
@@ -82,7 +82,7 @@ public:
[[nodiscard]] const MachinePassContract &contract() const noexcept override;
[[nodiscard]] Expected<MachinePassResult> run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &Analyses) override;
+ MachineFunctionAnalysisManager &Analyses) override;
private:
const VirtRegMap *Mapping;
diff --git a/backend/include/rcc/IR/PassInstrumentation.h b/backend/include/rcc/IR/PassInstrumentation.h
new file mode 100644
index 0000000..082ec81
--- /dev/null
+++ b/backend/include/rcc/IR/PassInstrumentation.h
@@ -0,0 +1,227 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef RCC_IR_PASSINSTRUMENTATION_H
+#define RCC_IR_PASSINSTRUMENTATION_H
+
+#include "rcc/CodeGen/MachineFunctionAnalysisManager.h"
+
+#include <cstdint>
+#include <functional>
+#include <mutex>
+#include <optional>
+#include <string>
+#include <string_view>
+#include <unordered_map>
+#include <vector>
+
+namespace rcc {
+
+class CompilationUnit;
+class MachineFunction;
+class TargetDescription;
+struct MachinePassResult;
+struct CompilationUnitPassResult;
+
+enum class InstrumentationPhase : std::uint8_t {
+ Before,
+ After,
+};
+
+struct InstrumentationStatistic final {
+ std::string Name;
+ bool IsAnalysis = false;
+ std::uint64_t Invocations = 0;
+ std::uint64_t CacheHits = 0;
+ std::uint64_t Changes = 0;
+ std::uint64_t Failures = 0;
+ std::uint64_t TotalNanoseconds = 0;
+};
+
+struct MachineActionID final {
+ std::string Pass;
+ std::string Rule;
+ MachineFunctionStableID Function;
+ MachineInstrStableID Instruction;
+
+ [[nodiscard]] std::string toString() const;
+
+ friend bool operator==(const MachineActionID &, const MachineActionID &) = default;
+};
+
+struct MachineActionEvent final {
+ MachineActionID ID;
+ std::uint64_t Cost = 0;
+ bool Accepted = false;
+
+ friend bool operator==(const MachineActionEvent &, const MachineActionEvent &) = default;
+};
+
+class MachinePassInstrumentation final {
+public:
+ using BeforeCallback = std::function<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 AfterAnalysisCallback =
+ std::function<void(std::string_view, const MachineFunction &, 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]] 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:
+ struct BufferedEvents final {
+ const TargetDescription *Target = nullptr;
+ std::vector<std::function<void()>> Events;
+ };
+
+ [[nodiscard]] bool bufferFunctionEvent(const MachineFunction &Function,
+ std::function<void(const MachineFunction &)> Replay) const;
+ void beginBuffering(BufferedEvents &Buffer, const TargetDescription &Target) const noexcept;
+ void endBuffering() const noexcept;
+ void replayBufferedEvents(BufferedEvents &Buffer) const;
+
+ void before(std::string_view Name, const MachineFunction &Function) const;
+ void after(std::string_view Name, const MachineFunction &Function,
+ const MachinePassResult &Result, std::uint64_t Nanoseconds) const;
+ void failure(std::string_view Name, const MachineFunction &Function, const Error &ErrorValue,
+ std::uint64_t Nanoseconds = 0) const;
+ void beforeAnalysis(std::string_view Name, const MachineFunction &Function) const;
+ void afterAnalysis(std::string_view Name, const MachineFunction &Function, bool CacheHit,
+ std::uint64_t Nanoseconds) const;
+ void analysisFailure(std::string_view Name, const MachineFunction &Function,
+ const Error &ErrorValue, std::uint64_t Nanoseconds) const;
+ void change(std::string_view Name, const MachineFunction &Function, MachinePassChanges Changes,
+ bool FingerprintChanged) const;
+
+ void beforeUnit(std::string_view Name, const CompilationUnit &Unit) const;
+ void afterUnit(std::string_view Name, const CompilationUnit &Unit,
+ const CompilationUnitPassResult &Result, std::uint64_t Nanoseconds) const;
+ void unitFailure(std::string_view Name, const CompilationUnit &Unit, const Error &ErrorValue,
+ std::uint64_t Nanoseconds = 0) const;
+ void beforeAnalysis(std::string_view Name, const CompilationUnit &Unit) const;
+ void afterAnalysis(std::string_view Name, const CompilationUnit &Unit, bool CacheHit,
+ std::uint64_t Nanoseconds) const;
+ void analysisFailure(std::string_view Name, const CompilationUnit &Unit, const Error &ErrorValue,
+ std::uint64_t Nanoseconds) const;
+
+ [[nodiscard]] InstrumentationStatistic &statistic(std::string_view Name, bool IsAnalysis) const;
+
+ mutable std::mutex Mutex;
+ mutable std::mutex ActionMutex;
+ std::vector<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;
+
+ static thread_local BufferedEvents *ActiveBuffer;
+
+ template <typename, typename> friend struct AnalysisManagerInstrumentation;
+ template <typename, typename, typename> friend struct PassManagerCallbacks;
+};
+
+class MachineActionReplay final {
+public:
+ template <typename AnalysisManagerT>
+ explicit MachineActionReplay(AnalysisManagerT &Analyses)
+ : Request([&Analyses](std::string_view Rule, const MachineFunction &Function,
+ MachineInstrStableID Instruction, std::uint64_t Cost) {
+ return Analyses.requestAction(Rule, Function, Instruction, Cost);
+ }) {}
+
+ template <typename AnalysisManagerT>
+ MachineActionReplay(
+ AnalysisManagerT &Analyses,
+ const std::unordered_map<MachineInstrStableID, MachineInstrStableID> &SourceToClone)
+ : MachineActionReplay(Analyses) {
+ for (const auto &[Source, Clone] : SourceToClone)
+ RecordingInstructionIDs.try_emplace(Clone, Source);
+ }
+
+ [[nodiscard]] Expected<bool> request(std::string_view Rule, const MachineFunction &Function,
+ MachineInstrStableID Instruction = {},
+ std::uint64_t Cost = 1);
+ void beginReplay() noexcept;
+ [[nodiscard]] Expected<void> finishReplay() const;
+
+private:
+ struct Decision final {
+ std::string Rule;
+ MachineFunctionStableID Function;
+ MachineInstrStableID Instruction;
+ std::uint64_t Cost = 0;
+ bool Accepted = false;
+ };
+
+ std::function<Expected<bool>(std::string_view, const MachineFunction &, MachineInstrStableID,
+ std::uint64_t)>
+ Request;
+ std::unordered_map<MachineInstrStableID, MachineInstrStableID> RecordingInstructionIDs;
+ std::vector<Decision> Decisions;
+ std::size_t NextDecision = 0;
+ bool IsReplaying = false;
+};
+
+} // namespace rcc
+
+#endif // RCC_IR_PASSINSTRUMENTATION_H
diff --git a/backend/include/rcc/IR/PassManager.h b/backend/include/rcc/IR/PassManager.h
new file mode 100644
index 0000000..b3ab088
--- /dev/null
+++ b/backend/include/rcc/IR/PassManager.h
@@ -0,0 +1,531 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef RCC_IR_PASSMANAGER_H
+#define RCC_IR_PASSMANAGER_H
+
+#include "rcc/Support/Error.h"
+
+#include <algorithm>
+#include <chrono>
+#include <concepts>
+#include <cstddef>
+#include <cstdint>
+#include <functional>
+#include <memory>
+#include <optional>
+#include <ranges>
+#include <set>
+#include <span>
+#include <string>
+#include <string_view>
+#include <unordered_map>
+#include <unordered_set>
+#include <utility>
+#include <vector>
+
+namespace rcc {
+
+class TargetDescription;
+
+using AnalysisID = const void *;
+
+class PreservedAnalyses final {
+public:
+ [[nodiscard]] static PreservedAnalyses all() noexcept {
+ PreservedAnalyses Result;
+ Result.PreserveAll = true;
+ return Result;
+ }
+
+ [[nodiscard]] static PreservedAnalyses none() noexcept {
+ return {};
+ }
+
+ void preserve(AnalysisID ID) {
+ if (ID != nullptr)
+ Preserved.insert(ID);
+ }
+
+ template <typename AnalysisT> void preserve() {
+ preserve(analysisID<AnalysisT>());
+ }
+
+ [[nodiscard]] bool preserves(AnalysisID ID) const noexcept {
+ return PreserveAll || (ID != nullptr && Preserved.contains(ID));
+ }
+
+ [[nodiscard]] bool preservesAll() const noexcept {
+ return PreserveAll;
+ }
+
+ template <typename AnalysisT> [[nodiscard]] static AnalysisID analysisID() noexcept {
+ static const std::uint8_t Token = 0;
+ return &Token;
+ }
+
+private:
+ bool PreserveAll = false;
+ std::unordered_set<AnalysisID> Preserved;
+};
+
+enum class PassThreadSafety : std::uint8_t {
+ NotThreadSafe,
+ ThreadSafe,
+};
+
+struct PassParameter final {
+ std::string Name;
+ std::string Description;
+ std::optional<std::string> DefaultValue;
+ bool Required = false;
+};
+
+template <typename IRUnitT, typename InstrumentationT> struct AnalysisManagerInstrumentation {
+ static void beforeAnalysis(InstrumentationT *, std::string_view, const IRUnitT &) {}
+ static void afterAnalysis(InstrumentationT *, std::string_view, const IRUnitT &, bool,
+ std::uint64_t) {}
+ static void analysisFailure(InstrumentationT *, std::string_view, const IRUnitT &, const Error &,
+ std::uint64_t) {}
+
+ template <typename InstructionT>
+ [[nodiscard]] static Expected<bool> requestAction(InstrumentationT *, std::string_view,
+ std::string_view, const IRUnitT &, InstructionT,
+ std::uint64_t) {
+ return true;
+ }
+};
+
+template <typename ChangeT> struct AnalysisRegistration final {
+ AnalysisID ID = nullptr;
+ std::string Name;
+ std::vector<AnalysisID> Dependencies;
+ ChangeT InvalidatedBy = ChangeT::all();
+ PassThreadSafety ThreadSafety = PassThreadSafety::NotThreadSafe;
+};
+
+template <typename IRUnitT, typename PassT, typename OptionsT> struct PassManagerCallbacks;
+
+template <typename IRUnitT, typename PassT, typename OptionsT> class PassManager {
+public:
+ using PassList = std::vector<std::unique_ptr<PassT>>;
+ using Callbacks = PassManagerCallbacks<IRUnitT, PassT, OptionsT>;
+
+ explicit PassManager(OptionsT Options = {}) : Options(Options) {}
+ PassManager(const PassManager &) = delete;
+ PassManager &operator=(const PassManager &) = delete;
+ PassManager(PassManager &&) = default;
+ PassManager &operator=(PassManager &&) = default;
+ ~PassManager() = default;
+
+ [[nodiscard]] Expected<void> addPass(std::unique_ptr<PassT> Pass) {
+ if (!Pass)
+ return makeUnexpected(ErrorCode::InvalidArgument, "pass manager cannot add a null pass");
+ auto Validation = Callbacks::validate(*Pass);
+ if (!Validation)
+ return std::unexpected(Validation.error());
+ Passes.push_back(std::move(Pass));
+ return {};
+ }
+
+ template <typename... Args>
+ [[nodiscard]] Expected<void> run(IRUnitT &Unit, Args &&...Arguments) const {
+ return Callbacks::run(Passes, Options, Unit, std::forward<Args>(Arguments)...);
+ }
+
+ template <typename... Args>
+ [[nodiscard]] Expected<void> runFunctions(Args &&...Arguments) const
+ requires requires(const PassList &InputPasses, const OptionsT &InputOptions,
+ Args &&...InputArguments) {
+ Callbacks::runFunctions(InputPasses, InputOptions, std::forward<Args>(InputArguments)...);
+ }
+ {
+ return Callbacks::runFunctions(Passes, Options, std::forward<Args>(Arguments)...);
+ }
+
+ [[nodiscard]] std::size_t size() const noexcept {
+ return Passes.size();
+ }
+
+ [[nodiscard]] PassList takePasses() && noexcept {
+ return std::move(Passes);
+ }
+
+private:
+ PassList Passes;
+ OptionsT Options;
+};
+
+template <typename IRUnitT, typename RegistrationT, typename ChangeT, typename InstrumentationT>
+class AnalysisManager {
+public:
+ using Self = AnalysisManager<IRUnitT, RegistrationT, ChangeT, InstrumentationT>;
+
+ AnalysisManager() = default;
+ AnalysisManager(const AnalysisManager &) = delete;
+ AnalysisManager &operator=(const AnalysisManager &) = delete;
+ AnalysisManager(AnalysisManager &&) = delete;
+ AnalysisManager &operator=(AnalysisManager &&) = delete;
+ ~AnalysisManager() = default;
+
+ template <typename AnalysisT> [[nodiscard]] static AnalysisID id() noexcept {
+ return PreservedAnalyses::analysisID<AnalysisT>();
+ }
+
+ template <typename AnalysisT>
+ [[nodiscard]] Expected<void> registerAnalysis(RegistrationT Registration = {}) {
+ using ResultT = typename AnalysisT::Result;
+ if (Registration.ID == nullptr)
+ Registration.ID = id<AnalysisT>();
+ if (Registration.Name.empty()) {
+ if constexpr (requires {
+ { AnalysisT::name() } -> std::convertible_to<std::string_view>;
+ })
+ Registration.Name = std::string(AnalysisT::name());
+ else
+ Registration.Name = "unnamed-analysis";
+ }
+
+ ErasedRunner Runner = [](IRUnitT &Unit, const TargetDescription &Target,
+ Self &Manager) -> Expected<std::shared_ptr<void>> {
+ auto Computed = AnalysisT::run(Unit, Target, Manager);
+ if (!Computed)
+ return std::unexpected(Computed.error());
+ return std::shared_ptr<void>(new ResultT(std::move(*Computed)),
+ [](void *Value) { delete static_cast<ResultT *>(Value); });
+ };
+ ErasedInvalidator Invalidator = [](void *Value, const IRUnitT &Unit,
+ const PreservedAnalyses &Preserved) -> bool {
+ if constexpr (requires(ResultT &Result, const IRUnitT &InputUnit,
+ const PreservedAnalyses &Analyses) {
+ { Result.invalidate(InputUnit, Analyses) } -> std::convertible_to<bool>;
+ })
+ return static_cast<ResultT *>(Value)->invalidate(Unit, Preserved);
+ return true;
+ };
+ return registerAnalysisImpl(std::move(Registration), std::move(Runner), std::move(Invalidator));
+ }
+
+ template <typename AnalysisT>
+ [[nodiscard]] Expected<typename AnalysisT::Result *> getResult(IRUnitT &Unit,
+ const TargetDescription &Target) {
+ const AnalysisID Key = id<AnalysisT>();
+ if (!isRegistered(Key)) {
+ auto Registered = registerAnalysis<AnalysisT>();
+ if (!Registered)
+ return std::unexpected(Registered.error());
+ }
+ auto Result = getResultImpl(Key, Unit, Target);
+ if (!Result)
+ return std::unexpected(Result.error());
+ return static_cast<typename AnalysisT::Result *>(*Result);
+ }
+
+ [[nodiscard]] Expected<void *> getResultByID(AnalysisID ID, IRUnitT &Unit,
+ const TargetDescription &Target) {
+ return getResultImpl(ID, Unit, Target);
+ }
+
+ void invalidate(IRUnitT &Unit, const PreservedAnalyses &Preserved, ChangeT Changes) noexcept {
+ const auto UnitPosition = Cache.find(&Unit);
+ if (UnitPosition == Cache.end() || Preserved.preservesAll() || Changes.empty())
+ return;
+
+ std::set<AnalysisID> Invalid;
+ for (auto &[ID, Entry] : UnitPosition->second) {
+ if (Preserved.preserves(ID))
+ continue;
+ const auto Registration = Registry.find(ID);
+ if (Registration == Registry.end() ||
+ Registration->second.Info.InvalidatedBy.intersects(Changes)) {
+ const bool ShouldInvalidate =
+ Registration == Registry.end() || !Entry.Value || !Registration->second.Invalidator ||
+ Registration->second.Invalidator(Entry.Value.get(), Unit, Preserved);
+ if (ShouldInvalidate)
+ Invalid.insert(ID);
+ }
+ }
+
+ bool Added = true;
+ while (Added) {
+ Added = false;
+ for (const auto &[ID, Entry] : UnitPosition->second) {
+ (void)Entry;
+ if (Invalid.contains(ID) || Preserved.preserves(ID))
+ continue;
+ const auto Registration = Registry.find(ID);
+ if (Registration != Registry.end() &&
+ std::ranges::any_of(
+ Registration->second.Info.Dependencies,
+ [&Invalid](AnalysisID Dependency) { return Invalid.contains(Dependency); }))
+ Added = Invalid.insert(ID).second || Added;
+ }
+ }
+
+ for (const AnalysisID ID : Invalid)
+ UnitPosition->second.erase(ID);
+ if (UnitPosition->second.empty())
+ Cache.erase(UnitPosition);
+ }
+
+ void invalidate(IRUnitT &Unit, const PreservedAnalyses &Preserved) noexcept {
+ invalidate(Unit, Preserved, ChangeT::all());
+ }
+
+ [[nodiscard]] bool hasCached(const IRUnitT &Unit, AnalysisID ID) const noexcept {
+ const auto UnitPosition = Cache.find(const_cast<IRUnitT *>(&Unit));
+ if (UnitPosition == Cache.end())
+ return false;
+ const auto AnalysisPosition = UnitPosition->second.find(ID);
+ return AnalysisPosition != UnitPosition->second.end() && AnalysisPosition->second.Value;
+ }
+
+ [[nodiscard]] std::size_t cachedResultCount(const IRUnitT &Unit) const noexcept {
+ const auto Position = Cache.find(const_cast<IRUnitT *>(&Unit));
+ return Position == Cache.end() ? 0 : Position->second.size();
+ }
+
+ [[nodiscard]] bool isRegistered(AnalysisID ID) const noexcept {
+ return ID != nullptr && Registry.contains(ID);
+ }
+
+ void clear(IRUnitT &Unit) noexcept {
+ Cache.erase(&Unit);
+ ActiveComputations.erase(&Unit);
+ }
+
+ void clearAll() noexcept {
+ Cache.clear();
+ ActiveComputations.clear();
+ }
+
+ [[nodiscard]] Expected<std::unique_ptr<Self>> forkEmpty() const {
+ if (!ActiveComputations.empty())
+ return makeUnexpected(ErrorCode::InvalidArgument,
+ "cannot fork an analysis manager during analysis computation");
+ auto Result = std::make_unique<Self>();
+ Result->Registry = Registry;
+ return Result;
+ }
+
+ [[nodiscard]] Expected<void> replaceRegistrations(Self &&Source) {
+ if (!Cache.empty() || !ActiveComputations.empty() || !Source.Cache.empty() ||
+ !Source.ActiveComputations.empty())
+ return makeUnexpected(ErrorCode::InvalidArgument,
+ "analysis registrations can only be replaced on empty managers");
+ Registry = std::move(Source.Registry);
+ return {};
+ }
+
+ [[nodiscard]] Expected<void>
+ validateParallelRequirements(std::span<const AnalysisID> RequiredAnalyses) const {
+ std::vector<AnalysisID> Worklist(RequiredAnalyses.begin(), RequiredAnalyses.end());
+ std::unordered_set<AnalysisID> Visited;
+ for (std::size_t Index = 0; Index < Worklist.size(); ++Index) {
+ const AnalysisID ID = Worklist[Index];
+ if (ID == nullptr || !Visited.insert(ID).second)
+ continue;
+ const auto Position = Registry.find(ID);
+ if (Position == Registry.end())
+ return makeUnexpected(ErrorCode::InvalidArgument,
+ "parallel pass requires an unregistered analysis");
+ if (Position->second.Info.ThreadSafety != PassThreadSafety::ThreadSafe)
+ return makeUnexpected(ErrorCode::InvalidArgument, "parallel pipeline requires analysis '" +
+ Position->second.Info.Name +
+ "' to be marked thread-safe");
+ Worklist.insert(Worklist.end(), Position->second.Info.Dependencies.begin(),
+ Position->second.Info.Dependencies.end());
+ }
+ return {};
+ }
+
+ void setInstrumentation(InstrumentationT *NewInstrumentation) noexcept {
+ Instrumentation = NewInstrumentation;
+ }
+
+ void setActivePass(std::string Name) {
+ ActivePass = std::move(Name);
+ }
+
+ template <typename InstructionT>
+ [[nodiscard]] Expected<bool> requestAction(std::string_view Rule, const IRUnitT &Unit,
+ InstructionT Instruction, std::uint64_t Cost = 1) {
+ if (Rule.empty() || Cost == 0)
+ return makeUnexpected(ErrorCode::InvalidArgument,
+ "pass action requires a name and nonzero cost");
+ if (Instrumentation == nullptr)
+ return true;
+ return AnalysisManagerInstrumentation<IRUnitT, InstrumentationT>::requestAction(
+ Instrumentation, ActivePass.empty() ? "unscoped" : ActivePass, Rule, Unit, Instruction,
+ Cost);
+ }
+
+ [[nodiscard]] Expected<bool> requestAction(std::string_view Rule, const IRUnitT &Unit,
+ std::uint64_t Cost = 1) {
+ if (Rule.empty() || Cost == 0)
+ return makeUnexpected(ErrorCode::InvalidArgument,
+ "pass action requires a name and nonzero cost");
+ if (Instrumentation == nullptr)
+ return true;
+ return AnalysisManagerInstrumentation<IRUnitT, InstrumentationT>::requestAction(
+ Instrumentation, ActivePass.empty() ? "unscoped" : ActivePass, Rule, Unit, nullptr, Cost);
+ }
+
+ [[nodiscard]] const std::string &activePass() const noexcept {
+ return ActivePass;
+ }
+
+private:
+ using ErasedRunner =
+ std::function<Expected<std::shared_ptr<void>>(IRUnitT &, const TargetDescription &, Self &)>;
+ using ErasedInvalidator = std::function<bool(void *, const IRUnitT &, const PreservedAnalyses &)>;
+
+ struct RegisteredAnalysis final {
+ RegistrationT Info;
+ ErasedRunner Runner;
+ ErasedInvalidator Invalidator;
+ };
+
+ struct CacheEntry final {
+ std::shared_ptr<void> Value;
+ AnalysisID ID = nullptr;
+ };
+
+ [[nodiscard]] static bool hasDuplicateAnalysisIDs(std::span<const AnalysisID> IDs) {
+ std::unordered_set<AnalysisID> Unique;
+ for (const AnalysisID ID : IDs) {
+ if (ID == nullptr || !Unique.insert(ID).second)
+ return true;
+ }
+ return false;
+ }
+
+ [[nodiscard]] Expected<void> registerAnalysisImpl(RegistrationT Registration, ErasedRunner Runner,
+ ErasedInvalidator Invalidator) {
+ if (Registration.ID == nullptr || Registration.Name.empty() || !Runner || !Invalidator)
+ return makeUnexpected(ErrorCode::InvalidArgument, "analysis registration is incomplete");
+ if (hasDuplicateAnalysisIDs(Registration.Dependencies))
+ return makeUnexpected(ErrorCode::InvalidArgument,
+ "analysis dependencies must be non-null and unique");
+ if (std::ranges::find(Registration.Dependencies, Registration.ID) !=
+ Registration.Dependencies.end())
+ return makeUnexpected(ErrorCode::InvalidArgument,
+ "analysis cannot directly depend on itself");
+ if (Registry.contains(Registration.ID))
+ return makeUnexpected(ErrorCode::InvalidArgument, "analysis ID is already registered");
+ if (std::ranges::any_of(Registry, [&Registration](const auto &Entry) {
+ return Entry.second.Info.Name == Registration.Name;
+ }))
+ return makeUnexpected(ErrorCode::InvalidArgument, "analysis name is already registered");
+ Registry.emplace(Registration.ID, RegisteredAnalysis{std::move(Registration), std::move(Runner),
+ std::move(Invalidator)});
+ return {};
+ }
+
+ [[nodiscard]] Expected<void *> getResultImpl(AnalysisID ID, IRUnitT &Unit,
+ const TargetDescription &Target) {
+ if (ID == nullptr)
+ return makeUnexpected(ErrorCode::InvalidArgument, "analysis ID cannot be null");
+ auto &UnitCache = Cache[&Unit];
+ if (const auto Cached = UnitCache.find(ID); Cached != UnitCache.end() && Cached->second.Value) {
+ const auto Registration = Registry.find(ID);
+ const std::string_view Name = Registration == Registry.end()
+ ? std::string_view{"unknown-analysis"}
+ : std::string_view{Registration->second.Info.Name};
+ if (Instrumentation != nullptr)
+ AnalysisManagerInstrumentation<IRUnitT, InstrumentationT>::afterAnalysis(
+ Instrumentation, Name, Unit, true, 0);
+ return Cached->second.Value.get();
+ }
+
+ const auto RegistrationPosition = Registry.find(ID);
+ if (RegistrationPosition == Registry.end())
+ return makeUnexpected(ErrorCode::InvalidArgument, "analysis ID is not registered");
+ const RegisteredAnalysis &Registration = RegistrationPosition->second;
+ auto &Stack = ActiveComputations[&Unit];
+ if (std::ranges::find(Stack, ID) != Stack.end()) {
+ Error Failure(ErrorCode::InvalidArgument,
+ "analysis dependency cycle reaches '" + Registration.Info.Name + "'");
+ if (Instrumentation != nullptr)
+ AnalysisManagerInstrumentation<IRUnitT, InstrumentationT>::analysisFailure(
+ Instrumentation, Registration.Info.Name, Unit, Failure, 0);
+ return std::unexpected(std::move(Failure));
+ }
+
+ if (Instrumentation != nullptr)
+ AnalysisManagerInstrumentation<IRUnitT, InstrumentationT>::beforeAnalysis(
+ Instrumentation, Registration.Info.Name, Unit);
+ const auto Start = std::chrono::steady_clock::now();
+ Stack.push_back(ID);
+ for (const AnalysisID Dependency : Registration.Info.Dependencies) {
+ if (!Registry.contains(Dependency)) {
+ Stack.pop_back();
+ if (Stack.empty())
+ ActiveComputations.erase(&Unit);
+ return makeUnexpected(ErrorCode::InvalidArgument,
+ "analysis depends on an unregistered analysis");
+ }
+ auto DependencyResult = getResultImpl(Dependency, Unit, Target);
+ if (!DependencyResult) {
+ Stack.pop_back();
+ if (Stack.empty())
+ ActiveComputations.erase(&Unit);
+ Error Failure = DependencyResult.error();
+ std::string Message = "analysis '" + Registration.Info.Name + "' failed: ";
+ Message.append(Failure.message());
+ Failure = Error(Failure.code(), std::move(Message));
+ if (Instrumentation != nullptr)
+ AnalysisManagerInstrumentation<IRUnitT, InstrumentationT>::analysisFailure(
+ Instrumentation, Registration.Info.Name, Unit, Failure, elapsedNanoseconds(Start));
+ return std::unexpected(std::move(Failure));
+ }
+ }
+
+ auto Computed = Registration.Runner(Unit, Target, *this);
+ Stack.pop_back();
+ if (Stack.empty())
+ ActiveComputations.erase(&Unit);
+ const std::uint64_t Duration = elapsedNanoseconds(Start);
+ if (!Computed) {
+ Error Failure = Computed.error();
+ std::string Message = "analysis '" + Registration.Info.Name + "' failed: ";
+ Message.append(Failure.message());
+ Failure = Error(Failure.code(), std::move(Message));
+ if (Instrumentation != nullptr)
+ AnalysisManagerInstrumentation<IRUnitT, InstrumentationT>::analysisFailure(
+ Instrumentation, Registration.Info.Name, Unit, Failure, Duration);
+ return std::unexpected(std::move(Failure));
+ }
+ if (!*Computed) {
+ Error Failure(ErrorCode::InternalError,
+ "analysis '" + Registration.Info.Name + "' returned a null result");
+ if (Instrumentation != nullptr)
+ AnalysisManagerInstrumentation<IRUnitT, InstrumentationT>::analysisFailure(
+ Instrumentation, Registration.Info.Name, Unit, Failure, Duration);
+ return std::unexpected(std::move(Failure));
+ }
+
+ void *Result = Computed->get();
+ UnitCache.emplace(ID, CacheEntry{std::move(*Computed), ID});
+ if (Instrumentation != nullptr)
+ AnalysisManagerInstrumentation<IRUnitT, InstrumentationT>::afterAnalysis(
+ Instrumentation, Registration.Info.Name, Unit, false, Duration);
+ return Result;
+ }
+
+ [[nodiscard]] static std::uint64_t
+ elapsedNanoseconds(std::chrono::steady_clock::time_point Start) noexcept {
+ const auto Elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(
+ std::chrono::steady_clock::now() - Start);
+ return Elapsed.count() <= 0 ? 0 : static_cast<std::uint64_t>(Elapsed.count());
+ }
+
+ std::unordered_map<AnalysisID, RegisteredAnalysis> Registry;
+ std::unordered_map<IRUnitT *, std::unordered_map<AnalysisID, CacheEntry>> Cache;
+ std::unordered_map<IRUnitT *, std::vector<AnalysisID>> ActiveComputations;
+ InstrumentationT *Instrumentation = nullptr;
+ std::string ActivePass;
+};
+
+} // namespace rcc
+
+#endif // RCC_IR_PASSMANAGER_H
diff --git a/backend/include/rcc/Target/RISCV/RISCVPipeline.h b/backend/include/rcc/Target/RISCV/RISCVPipeline.h
index ba0428b..8b27032 100644
--- a/backend/include/rcc/Target/RISCV/RISCVPipeline.h
+++ b/backend/include/rcc/Target/RISCV/RISCVPipeline.h
@@ -3,7 +3,7 @@
#ifndef RCC_TARGET_RISCV_RISCVPIPELINE_H
#define RCC_TARGET_RISCV_RISCVPIPELINE_H
-#include "rcc/CodeGen/MachinePass.h"
+#include "rcc/CodeGen/MachinePassManager.h"
#include "rcc/Support/Error.h"
#include "rcc/Target/RISCV/RISCVSubtarget.h"
@@ -19,7 +19,7 @@ class TargetDescription;
namespace riscv {
-[[nodiscard]] Expected<void> addCanonicalPipeline(MachinePassManager &Pipeline,
+[[nodiscard]] Expected<void> addCanonicalPipeline(MachineFunctionPassManager &Pipeline,
const MachineFunction &Function,
const RISCVSubtarget &Subtarget);
[[nodiscard]] Expected<std::unique_ptr<MachineFunctionPass>>
diff --git a/backend/include/rcc/Tooling/BackendDriver.h b/backend/include/rcc/Tooling/BackendDriver.h
index 7b62b6d..6b04de9 100644
--- a/backend/include/rcc/Tooling/BackendDriver.h
+++ b/backend/include/rcc/Tooling/BackendDriver.h
@@ -3,7 +3,7 @@
#ifndef RCC_TOOLING_BACKENDDRIVER_H
#define RCC_TOOLING_BACKENDDRIVER_H
-#include "rcc/CodeGen/MachinePass.h"
+#include "rcc/CodeGen/MachinePassManager.h"
#include "rcc/Support/Error.h"
#include "rcc/Tooling/ArtifactStore.h"
#include "rcc/Tooling/PipelineDriver.h"
diff --git a/backend/include/rcc/Tooling/PipelineDriver.h b/backend/include/rcc/Tooling/PipelineDriver.h
index 5d2dc45..849b2f7 100644
--- a/backend/include/rcc/Tooling/PipelineDriver.h
+++ b/backend/include/rcc/Tooling/PipelineDriver.h
@@ -3,7 +3,7 @@
#ifndef RCC_TOOLING_PIPELINEDRIVER_H
#define RCC_TOOLING_PIPELINEDRIVER_H
-#include "rcc/CodeGen/MachinePass.h"
+#include "rcc/CodeGen/MachinePassManager.h"
#include "rcc/MIR/MIRDocument.h"
#include "rcc/Tooling/BackendInvocation.h"
diff --git a/backend/lib/CodeGen/CMakeLists.txt b/backend/lib/CodeGen/CMakeLists.txt
index 470571d..4488903 100644
--- a/backend/lib/CodeGen/CMakeLists.txt
+++ b/backend/lib/CodeGen/CMakeLists.txt
@@ -48,7 +48,7 @@ set(
MachineMetadata.cpp
MachineOperand.cpp
MachineOptimizationPipeline.cpp
- MachinePass.cpp
+ MachinePassManager.cpp
MachinePseudoExpansion.cpp
MachineRegisterInfo.cpp
MachineScheduler.cpp
@@ -136,7 +136,10 @@ set(
"${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/MachineMetadata.h"
"${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/MachineOperand.h"
"${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/MachineOptimizationPipeline.h"
- "${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/MachinePass.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/MachinePassManager.h"
"${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/MachinePseudoExpansion.h"
"${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/PrologueEpilogueInsertion.h"
"${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/RegisterPressure.h"
@@ -262,7 +265,7 @@ rcc_backend_register_format_files(
"${CMAKE_CURRENT_SOURCE_DIR}/MachineMetadata.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/MachineOperand.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/MachineOptimizationPipeline.cpp"
- "${CMAKE_CURRENT_SOURCE_DIR}/MachinePass.cpp"
+ "${CMAKE_CURRENT_SOURCE_DIR}/MachinePassManager.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/MachinePseudoExpansion.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/MachineRegisterInfo.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/MachineScheduler.cpp"
@@ -350,7 +353,7 @@ rcc_backend_register_tidy_files(
"${CMAKE_CURRENT_SOURCE_DIR}/MachineMetadata.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/MachineOperand.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/MachineOptimizationPipeline.cpp"
- "${CMAKE_CURRENT_SOURCE_DIR}/MachinePass.cpp"
+ "${CMAKE_CURRENT_SOURCE_DIR}/MachinePassManager.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/MachinePseudoExpansion.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/MachineRegisterInfo.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/MachineScheduler.cpp"
diff --git a/backend/lib/CodeGen/GlobalISel/InstructionSelect.cpp b/backend/lib/CodeGen/GlobalISel/InstructionSelect.cpp
index ff32eda..344e63e 100644
--- a/backend/lib/CodeGen/GlobalISel/InstructionSelect.cpp
+++ b/backend/lib/CodeGen/GlobalISel/InstructionSelect.cpp
@@ -194,7 +194,7 @@ const MachinePassContract &InstructionSelect::contract() const noexcept {
Expected<MachinePassResult> InstructionSelect::run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &Analyses) {
+ MachineFunctionAnalysisManager &Analyses) {
if (Info == nullptr)
return std::unexpected(passFailure("instruction select has no target behavior interface",
ErrorCode::InvalidArgument));
diff --git a/backend/lib/CodeGen/GlobalISel/Legalizer.cpp b/backend/lib/CodeGen/GlobalISel/Legalizer.cpp
index 60f388d..7781818 100644
--- a/backend/lib/CodeGen/GlobalISel/Legalizer.cpp
+++ b/backend/lib/CodeGen/GlobalISel/Legalizer.cpp
@@ -175,7 +175,7 @@ const MachinePassContract &Legalizer::contract() const noexcept {
Expected<MachinePassResult> Legalizer::run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &Analyses) {
+ MachineFunctionAnalysisManager &Analyses) {
if (Info == nullptr)
return std::unexpected(
passFailure("legalizer has no target behavior interface", ErrorCode::InvalidArgument));
diff --git a/backend/lib/CodeGen/GlobalISel/RegBankSelect.cpp b/backend/lib/CodeGen/GlobalISel/RegBankSelect.cpp
index c36c500..041ab74 100644
--- a/backend/lib/CodeGen/GlobalISel/RegBankSelect.cpp
+++ b/backend/lib/CodeGen/GlobalISel/RegBankSelect.cpp
@@ -122,7 +122,7 @@ const MachinePassContract &RegBankSelect::contract() const noexcept {
Expected<MachinePassResult> RegBankSelect::run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &) {
+ MachineFunctionAnalysisManager &) {
if (Info == nullptr)
return std::unexpected(passFailure("register-bank select has no target behavior interface",
ErrorCode::InvalidArgument));
diff --git a/backend/lib/CodeGen/InlineSpiller.cpp b/backend/lib/CodeGen/InlineSpiller.cpp
index 14de321..1d5ba10 100644
--- a/backend/lib/CodeGen/InlineSpiller.cpp
+++ b/backend/lib/CodeGen/InlineSpiller.cpp
@@ -7,7 +7,7 @@
#include "rcc/CodeGen/MachineIRBuilder.h"
#include "rcc/CodeGen/MachineInstr.h"
#include "rcc/CodeGen/MachineOperand.h"
-#include "rcc/CodeGen/MachinePass.h"
+#include "rcc/CodeGen/MachinePassManager.h"
#include "rcc/CodeGen/MachineRegisterInfo.h"
#include "rcc/CodeGen/Spiller.h"
#include "rcc/CodeGen/TargetDescription.h"
diff --git a/backend/lib/CodeGen/LiveIntervals.cpp b/backend/lib/CodeGen/LiveIntervals.cpp
index d8cb539..5a01693 100644
--- a/backend/lib/CodeGen/LiveIntervals.cpp
+++ b/backend/lib/CodeGen/LiveIntervals.cpp
@@ -307,12 +307,12 @@ Expected<void> LiveIntervalsAnalysis::Result::shrinkToUses(Register Reg,
bool LiveIntervalsAnalysis::Result::invalidate(const MachineFunction &,
const PreservedAnalyses &Preserved) const noexcept {
- return !Preserved.preserves(MachineAnalysisManager::id<LiveIntervalsAnalysis>());
+ return !Preserved.preserves(MachineFunctionAnalysisManager::id<LiveIntervalsAnalysis>());
}
Expected<LiveIntervalsAnalysis::Result>
LiveIntervalsAnalysis::run(MachineFunction &Function, const TargetDescription &Target,
- MachineAnalysisManager &Analyses) {
+ MachineFunctionAnalysisManager &Analyses) {
auto Indexes = Analyses.getResult<SlotIndexesAnalysis>(Function, Target);
if (!Indexes)
return std::unexpected(Indexes.error());
diff --git a/backend/lib/CodeGen/LiveVariables.cpp b/backend/lib/CodeGen/LiveVariables.cpp
index 7323e0d..201e09e 100644
--- a/backend/lib/CodeGen/LiveVariables.cpp
+++ b/backend/lib/CodeGen/LiveVariables.cpp
@@ -884,12 +884,12 @@ bool LiveVariablesAnalysis::Result::isUnitLiveOut(const MachineBasicBlock &Block
bool LiveVariablesAnalysis::Result::invalidate(const MachineFunction &,
const PreservedAnalyses &Preserved) const noexcept {
- return !Preserved.preserves(MachineAnalysisManager::id<LiveVariablesAnalysis>());
+ return !Preserved.preserves(MachineFunctionAnalysisManager::id<LiveVariablesAnalysis>());
}
-Expected<LiveVariablesAnalysis::Result> LiveVariablesAnalysis::run(MachineFunction &Function,
- const TargetDescription &Target,
- MachineAnalysisManager &) {
+Expected<LiveVariablesAnalysis::Result>
+LiveVariablesAnalysis::run(MachineFunction &Function, const TargetDescription &Target,
+ MachineFunctionAnalysisManager &) {
return computeLiveVariables(Function, Target);
}
const MachinePassContract &RebuildMachineLivenessPass::contract() const noexcept {
@@ -911,7 +911,7 @@ const MachinePassContract &RebuildMachineLivenessPass::contract() const noexcept
Expected<MachinePassResult> RebuildMachineLivenessPass::run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &) {
+ MachineFunctionAnalysisManager &) {
const MachineFunctionProperties Missing = contract().Requires.missingFrom(Function.properties());
if (!Missing.empty()) {
return makeUnexpected(ErrorCode::VerificationError,
@@ -976,11 +976,11 @@ Expected<void> verifyTrackedMachineLiveness(const MachineFunction &Function,
return {};
}
-Expected<void> registerStage11MachineAnalyses(MachineAnalysisManager &Analyses) {
+Expected<void> registerStage11MachineAnalyses(MachineFunctionAnalysisManager &Analyses) {
const std::array IDs{
- MachineAnalysisManager::id<SlotIndexesAnalysis>(),
- MachineAnalysisManager::id<LiveVariablesAnalysis>(),
- MachineAnalysisManager::id<LiveIntervalsAnalysis>(),
+ MachineFunctionAnalysisManager::id<SlotIndexesAnalysis>(),
+ MachineFunctionAnalysisManager::id<LiveVariablesAnalysis>(),
+ MachineFunctionAnalysisManager::id<LiveIntervalsAnalysis>(),
};
const std::size_t Registered = static_cast<std::size_t>(
std::ranges::count_if(IDs, [&Analyses](AnalysisID ID) { return Analyses.isRegistered(ID); }));
@@ -994,7 +994,7 @@ Expected<void> registerStage11MachineAnalyses(MachineAnalysisManager &Analyses)
auto Candidate = Analyses.forkEmpty();
if (!Candidate)
return std::unexpected(Candidate.error());
- MachineAnalysisManager &Staging = **Candidate;
+ MachineFunctionAnalysisManager &Staging = **Candidate;
auto Slots = Staging.registerAnalysis<SlotIndexesAnalysis>({
.Name = "SlotIndexes",
.Dependencies = {},
@@ -1015,8 +1015,8 @@ Expected<void> registerStage11MachineAnalyses(MachineAnalysisManager &Analyses)
return std::unexpected(Variables.error());
auto Intervals = Staging.registerAnalysis<LiveIntervalsAnalysis>({
.Name = "LiveIntervals",
- .Dependencies = {MachineAnalysisManager::id<SlotIndexesAnalysis>(),
- MachineAnalysisManager::id<LiveVariablesAnalysis>()},
+ .Dependencies = {MachineFunctionAnalysisManager::id<SlotIndexesAnalysis>(),
+ MachineFunctionAnalysisManager::id<LiveVariablesAnalysis>()},
.InvalidatedBy = {MachinePassChange::Instructions, MachinePassChange::Operands,
MachinePassChange::Registers, MachinePassChange::CFG,
MachinePassChange::BlockLayout, MachinePassChange::TargetState},
@@ -1024,8 +1024,7 @@ Expected<void> registerStage11MachineAnalyses(MachineAnalysisManager &Analyses)
});
if (!Intervals)
return std::unexpected(Intervals.error());
- Analyses.Registry = std::move(Staging.Registry);
- return {};
+ return Analyses.replaceRegistrations(std::move(Staging));
}
} // namespace rcc
diff --git a/backend/lib/CodeGen/MachineAnalyses.cpp b/backend/lib/CodeGen/MachineAnalyses.cpp
index 33dc14f..3f09636 100644
--- a/backend/lib/CodeGen/MachineAnalyses.cpp
+++ b/backend/lib/CodeGen/MachineAnalyses.cpp
@@ -263,7 +263,7 @@ const MachineBasicBlock *MachineDominatorTreeAnalysis::Result::nearestCommonDomi
Expected<MachineDominatorTreeAnalysis::Result>
MachineDominatorTreeAnalysis::run(MachineFunction &Function, const TargetDescription &,
- MachineAnalysisManager &) {
+ MachineFunctionAnalysisManager &) {
Result ResultValue;
auto Built = ResultValue.build(Function);
if (!Built)
@@ -287,9 +287,9 @@ bool MachineLoopAnalysis::Result::isIrreducible(const MachineBasicBlock &Block)
return IrreducibleBlocks.contains(&Block);
}
-Expected<MachineLoopAnalysis::Result> MachineLoopAnalysis::run(MachineFunction &Function,
- const TargetDescription &Target,
- MachineAnalysisManager &Analyses) {
+Expected<MachineLoopAnalysis::Result>
+MachineLoopAnalysis::run(MachineFunction &Function, const TargetDescription &Target,
+ MachineFunctionAnalysisManager &Analyses) {
auto Dominators = Analyses.getResult<MachineDominatorTreeAnalysis>(Function, Target);
if (!Dominators)
return std::unexpected(Dominators.error());
@@ -496,7 +496,7 @@ std::span<const MachineSuccessor> MachineBranchProbabilityAnalysis::Result::succ
Expected<MachineBranchProbabilityAnalysis::Result>
MachineBranchProbabilityAnalysis::run(MachineFunction &Function, const TargetDescription &,
- MachineAnalysisManager &) {
+ MachineFunctionAnalysisManager &) {
Result ResultValue;
const std::vector<MachineBasicBlock *> Blocks = linkedBlocks(Function);
const auto Order = blockOrder(Blocks);
@@ -522,7 +522,7 @@ MachineBlockFrequencyAnalysis::Result::frequency(const MachineBasicBlock &Block)
Expected<MachineBlockFrequencyAnalysis::Result>
MachineBlockFrequencyAnalysis::run(MachineFunction &Function, const TargetDescription &Target,
- MachineAnalysisManager &Analyses) {
+ MachineFunctionAnalysisManager &Analyses) {
auto Dominators = Analyses.getResult<MachineDominatorTreeAnalysis>(Function, Target);
auto Loops = Analyses.getResult<MachineLoopAnalysis>(Function, Target);
auto Probabilities = Analyses.getResult<MachineBranchProbabilityAnalysis>(Function, Target);
@@ -628,8 +628,9 @@ MachineAliasAnalysis::Result::alias(const MachineMemOperand &Left,
return Distance >= LowerSize ? MachineAliasResult::NoAlias : MachineAliasResult::PartialAlias;
}
-Expected<MachineAliasAnalysis::Result>
-MachineAliasAnalysis::run(MachineFunction &, const TargetDescription &, MachineAnalysisManager &) {
+Expected<MachineAliasAnalysis::Result> MachineAliasAnalysis::run(MachineFunction &,
+ const TargetDescription &,
+ MachineFunctionAnalysisManager &) {
return Result{};
}
@@ -659,7 +660,7 @@ std::span<const MachineMemoryDependency> MachineMemoryDependenceAnalysis::Result
Expected<MachineMemoryDependenceAnalysis::Result>
MachineMemoryDependenceAnalysis::run(MachineFunction &Function, const TargetDescription &Target,
- MachineAnalysisManager &Analyses) {
+ MachineFunctionAnalysisManager &Analyses) {
auto Alias = Analyses.getResult<MachineAliasAnalysis>(Function, Target);
if (!Alias)
return std::unexpected(Alias.error());
@@ -766,14 +767,14 @@ MachineMemoryDependenceAnalysis::run(MachineFunction &Function, const TargetDesc
return ResultValue;
}
-Expected<void> registerStage8MachineAnalyses(MachineAnalysisManager &Analyses) {
+Expected<void> registerStage8MachineAnalyses(MachineFunctionAnalysisManager &Analyses) {
const std::array IDs{
- MachineAnalysisManager::id<MachineDominatorTreeAnalysis>(),
- MachineAnalysisManager::id<MachineLoopAnalysis>(),
- MachineAnalysisManager::id<MachineBranchProbabilityAnalysis>(),
- MachineAnalysisManager::id<MachineBlockFrequencyAnalysis>(),
- MachineAnalysisManager::id<MachineAliasAnalysis>(),
- MachineAnalysisManager::id<MachineMemoryDependenceAnalysis>(),
+ MachineFunctionAnalysisManager::id<MachineDominatorTreeAnalysis>(),
+ MachineFunctionAnalysisManager::id<MachineLoopAnalysis>(),
+ MachineFunctionAnalysisManager::id<MachineBranchProbabilityAnalysis>(),
+ MachineFunctionAnalysisManager::id<MachineBlockFrequencyAnalysis>(),
+ MachineFunctionAnalysisManager::id<MachineAliasAnalysis>(),
+ MachineFunctionAnalysisManager::id<MachineMemoryDependenceAnalysis>(),
};
const std::size_t Registered = static_cast<std::size_t>(
std::ranges::count_if(IDs, [&Analyses](AnalysisID ID) { return Analyses.isRegistered(ID); }));
@@ -787,7 +788,7 @@ Expected<void> registerStage8MachineAnalyses(MachineAnalysisManager &Analyses) {
auto Candidate = Analyses.forkEmpty();
if (!Candidate)
return std::unexpected(Candidate.error());
- MachineAnalysisManager &Staging = **Candidate;
+ MachineFunctionAnalysisManager &Staging = **Candidate;
auto Dominators = Staging.registerAnalysis<MachineDominatorTreeAnalysis>({
.Name = "MachineDominatorTree",
@@ -799,7 +800,7 @@ Expected<void> registerStage8MachineAnalyses(MachineAnalysisManager &Analyses) {
return std::unexpected(Dominators.error());
auto Loops = Staging.registerAnalysis<MachineLoopAnalysis>({
.Name = "MachineLoopInfo",
- .Dependencies = {MachineAnalysisManager::id<MachineDominatorTreeAnalysis>()},
+ .Dependencies = {MachineFunctionAnalysisManager::id<MachineDominatorTreeAnalysis>()},
.InvalidatedBy = {MachinePassChange::CFG, MachinePassChange::BlockLayout},
.ThreadSafety = PassThreadSafety::ThreadSafe,
});
@@ -815,9 +816,9 @@ Expected<void> registerStage8MachineAnalyses(MachineAnalysisManager &Analyses) {
return std::unexpected(Probabilities.error());
auto Frequencies = Staging.registerAnalysis<MachineBlockFrequencyAnalysis>({
.Name = "MachineBlockFrequency",
- .Dependencies = {MachineAnalysisManager::id<MachineDominatorTreeAnalysis>(),
- MachineAnalysisManager::id<MachineLoopAnalysis>(),
- MachineAnalysisManager::id<MachineBranchProbabilityAnalysis>()},
+ .Dependencies = {MachineFunctionAnalysisManager::id<MachineDominatorTreeAnalysis>(),
+ MachineFunctionAnalysisManager::id<MachineLoopAnalysis>(),
+ MachineFunctionAnalysisManager::id<MachineBranchProbabilityAnalysis>()},
.InvalidatedBy = {MachinePassChange::CFG, MachinePassChange::BlockLayout},
.ThreadSafety = PassThreadSafety::ThreadSafe,
});
@@ -835,7 +836,7 @@ Expected<void> registerStage8MachineAnalyses(MachineAnalysisManager &Analyses) {
return std::unexpected(Alias.error());
auto MemoryDependence = Staging.registerAnalysis<MachineMemoryDependenceAnalysis>({
.Name = "MachineMemoryDependence",
- .Dependencies = {MachineAnalysisManager::id<MachineAliasAnalysis>()},
+ .Dependencies = {MachineFunctionAnalysisManager::id<MachineAliasAnalysis>()},
.InvalidatedBy = {MachinePassChange::Instructions, MachinePassChange::Operands,
MachinePassChange::CFG, MachinePassChange::BlockLayout,
MachinePassChange::Frame, MachinePassChange::ConstantPool,
@@ -844,8 +845,7 @@ Expected<void> registerStage8MachineAnalyses(MachineAnalysisManager &Analyses) {
});
if (!MemoryDependence)
return std::unexpected(MemoryDependence.error());
- Analyses.Registry = std::move(Staging.Registry);
- return {};
+ return Analyses.replaceRegistrations(std::move(Staging));
}
} // namespace rcc
diff --git a/backend/lib/CodeGen/MachineBlockPlacement.cpp b/backend/lib/CodeGen/MachineBlockPlacement.cpp
index daccba0..1e563e1 100644
--- a/backend/lib/CodeGen/MachineBlockPlacement.cpp
+++ b/backend/lib/CodeGen/MachineBlockPlacement.cpp
@@ -37,10 +37,10 @@ enum class PlacementClass : std::uint8_t {
.Clears = {},
.RequiredAnalyses =
{
- MachineAnalysisManager::id<MachineDominatorTreeAnalysis>(),
- MachineAnalysisManager::id<MachineBranchProbabilityAnalysis>(),
- MachineAnalysisManager::id<MachineBlockFrequencyAnalysis>(),
- MachineAnalysisManager::id<MachineLoopAnalysis>(),
+ MachineFunctionAnalysisManager::id<MachineDominatorTreeAnalysis>(),
+ MachineFunctionAnalysisManager::id<MachineBranchProbabilityAnalysis>(),
+ MachineFunctionAnalysisManager::id<MachineBlockFrequencyAnalysis>(),
+ MachineFunctionAnalysisManager::id<MachineLoopAnalysis>(),
},
.VerificationStage = PipelineStage::Selected,
};
@@ -101,9 +101,9 @@ const MachinePassContract &MachineBlockPlacementPass::contract() const noexcept
return placementContract();
}
-Expected<MachinePassResult> MachineBlockPlacementPass::run(MachineFunction &Function,
- const TargetDescription &Target,
- MachineAnalysisManager &Analyses) {
+Expected<MachinePassResult>
+MachineBlockPlacementPass::run(MachineFunction &Function, const TargetDescription &Target,
+ MachineFunctionAnalysisManager &Analyses) {
if (!Function.properties().containsAll(contract().Requires)) {
return makeUnexpected(ErrorCode::VerificationError,
"machine block placement requires selected PHI-free MachineIR");
@@ -113,7 +113,7 @@ Expected<MachinePassResult> MachineBlockPlacementPass::run(MachineFunction &Func
MachineFunctionCloneOptions{.NewStableID = Function.stableID(), .NewName = std::nullopt});
if (!Trial)
return std::unexpected(prefixedError(Trial.error(), "block placement setup failed: "));
- MachineAnalysisManager TrialAnalyses;
+ MachineFunctionAnalysisManager TrialAnalyses;
MachineActionReplay Actions(Analyses, Trial->InstructionStableIDs);
auto TrialResult = runImplementation(*Trial->ClonedFunction, Target, TrialAnalyses, Actions);
if (!TrialResult)
@@ -131,8 +131,8 @@ Expected<MachinePassResult> MachineBlockPlacementPass::run(MachineFunction &Func
}
Expected<MachinePassResult> MachineBlockPlacementPass::runImplementation(
- MachineFunction &Function, const TargetDescription &Target, MachineAnalysisManager &Analyses,
- MachineActionReplay &Actions) const {
+ MachineFunction &Function, const TargetDescription &Target,
+ MachineFunctionAnalysisManager &Analyses, MachineActionReplay &Actions) const {
auto Probabilities = Analyses.getResult<MachineBranchProbabilityAnalysis>(Function, Target);
if (!Probabilities)
return std::unexpected(Probabilities.error());
diff --git a/backend/lib/CodeGen/MachineBranchOptimization.cpp b/backend/lib/CodeGen/MachineBranchOptimization.cpp
index 5880dbc..c102931 100644
--- a/backend/lib/CodeGen/MachineBranchOptimization.cpp
+++ b/backend/lib/CodeGen/MachineBranchOptimization.cpp
@@ -301,7 +301,7 @@ const MachinePassContract &MachineBranchOptimizationPass::contract() const noexc
Expected<MachinePassResult> MachineBranchOptimizationPass::run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &) {
+ MachineFunctionAnalysisManager &) {
if (!Function.properties().containsAll(contract().Requires)) {
return makeUnexpected(ErrorCode::VerificationError,
"branch optimization requires selected PHI-free MachineIR");
diff --git a/backend/lib/CodeGen/MachineBranchRelaxation.cpp b/backend/lib/CodeGen/MachineBranchRelaxation.cpp
index 78640f1..c11ed8e 100644
--- a/backend/lib/CodeGen/MachineBranchRelaxation.cpp
+++ b/backend/lib/CodeGen/MachineBranchRelaxation.cpp
@@ -107,9 +107,9 @@ const MachinePassContract &MachineBranchRelaxationPass::contract() const noexcep
return relaxationContract();
}
-Expected<MachinePassResult> MachineBranchRelaxationPass::run(MachineFunction &Function,
- const TargetDescription &Target,
- MachineAnalysisManager &Analyses) {
+Expected<MachinePassResult>
+MachineBranchRelaxationPass::run(MachineFunction &Function, const TargetDescription &Target,
+ MachineFunctionAnalysisManager &Analyses) {
if (!Function.properties().containsAll(contract().Requires)) {
return makeUnexpected(ErrorCode::VerificationError,
"branch relaxation requires finalized frame and tracked liveness");
diff --git a/backend/lib/CodeGen/MachineCSE.cpp b/backend/lib/CodeGen/MachineCSE.cpp
index 9d80b4e..92fe1bd 100644
--- a/backend/lib/CodeGen/MachineCSE.cpp
+++ b/backend/lib/CodeGen/MachineCSE.cpp
@@ -33,7 +33,7 @@ namespace {
.Requires = {MachineFunctionProperty::IsSSA, MachineFunctionProperty::Selected},
.Sets = {},
.Clears = {},
- .RequiredAnalyses = {MachineAnalysisManager::id<MachineDominatorTreeAnalysis>()},
+ .RequiredAnalyses = {MachineFunctionAnalysisManager::id<MachineDominatorTreeAnalysis>()},
.VerificationStage = PipelineStage::Selected,
};
Value.ThreadSafety = PassThreadSafety::ThreadSafe;
@@ -314,7 +314,7 @@ const MachinePassContract &MachineCSEPass::contract() const noexcept {
Expected<MachinePassResult> MachineCSEPass::run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &Analyses) {
+ MachineFunctionAnalysisManager &Analyses) {
if (!Function.properties().containsAll(contract().Requires)) {
return makeUnexpected(ErrorCode::VerificationError,
"machine CSE requires selected SSA MachineIR");
@@ -325,7 +325,7 @@ Expected<MachinePassResult> MachineCSEPass::run(MachineFunction &Function,
if (!Trial) {
return std::unexpected(prefixedError(Trial.error(), "machine CSE transaction setup failed: "));
}
- MachineAnalysisManager TrialAnalyses;
+ MachineFunctionAnalysisManager TrialAnalyses;
auto TrialResult = runImplementation(*Trial->ClonedFunction, Target, TrialAnalyses);
if (!TrialResult)
return std::unexpected(TrialResult.error());
@@ -338,9 +338,9 @@ Expected<MachinePassResult> MachineCSEPass::run(MachineFunction &Function,
return Result;
}
-Expected<MachinePassResult> MachineCSEPass::runImplementation(MachineFunction &Function,
- const TargetDescription &Target,
- MachineAnalysisManager &Analyses) {
+Expected<MachinePassResult>
+MachineCSEPass::runImplementation(MachineFunction &Function, const TargetDescription &Target,
+ MachineFunctionAnalysisManager &Analyses) {
auto Dominators = Analyses.getResult<MachineDominatorTreeAnalysis>(Function, Target);
if (!Dominators)
return std::unexpected(Dominators.error());
diff --git a/backend/lib/CodeGen/MachineCombiner.cpp b/backend/lib/CodeGen/MachineCombiner.cpp
index df9c002..c3e9795 100644
--- a/backend/lib/CodeGen/MachineCombiner.cpp
+++ b/backend/lib/CodeGen/MachineCombiner.cpp
@@ -295,7 +295,7 @@ const MachinePassContract &MachineCombinerPass::contract() const noexcept {
Expected<MachinePassResult> MachineCombinerPass::run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &Analyses) {
+ MachineFunctionAnalysisManager &Analyses) {
if (!Function.properties().containsAll(contract().Requires)) {
return makeUnexpected(ErrorCode::VerificationError,
"machine combiner input does not satisfy its stage contract");
diff --git a/backend/lib/CodeGen/MachineCopyPropagation.cpp b/backend/lib/CodeGen/MachineCopyPropagation.cpp
index 581cb4f..9725399 100644
--- a/backend/lib/CodeGen/MachineCopyPropagation.cpp
+++ b/backend/lib/CodeGen/MachineCopyPropagation.cpp
@@ -290,9 +290,9 @@ const MachinePassContract &MachineCopyPropagationPass::contract() const noexcept
return copyPropagationContract(Stage);
}
-Expected<MachinePassResult> MachineCopyPropagationPass::run(MachineFunction &Function,
- const TargetDescription &Target,
- MachineAnalysisManager &Analyses) {
+Expected<MachinePassResult>
+MachineCopyPropagationPass::run(MachineFunction &Function, const TargetDescription &Target,
+ MachineFunctionAnalysisManager &Analyses) {
if (!Function.properties().containsAll(contract().Requires)) {
return makeUnexpected(ErrorCode::VerificationError,
"machine COPY propagation has unmet stage properties");
diff --git a/backend/lib/CodeGen/MachineDCE.cpp b/backend/lib/CodeGen/MachineDCE.cpp
index 4dd0e59..1c53c31 100644
--- a/backend/lib/CodeGen/MachineDCE.cpp
+++ b/backend/lib/CodeGen/MachineDCE.cpp
@@ -115,7 +115,7 @@ const MachinePassContract &MachineDCEPass::contract() const noexcept {
Expected<MachinePassResult> MachineDCEPass::run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &) {
+ MachineFunctionAnalysisManager &) {
if (!Function.properties().containsAll(contract().Requires)) {
return makeUnexpected(ErrorCode::VerificationError,
"machine DCE requires a selected machine function");
diff --git a/backend/lib/CodeGen/MachineFallthrough.cpp b/backend/lib/CodeGen/MachineFallthrough.cpp
index 5c58e67..608b703 100644
--- a/backend/lib/CodeGen/MachineFallthrough.cpp
+++ b/backend/lib/CodeGen/MachineFallthrough.cpp
@@ -26,7 +26,7 @@ namespace {
MachineFunctionProperty::NoVRegs, MachineFunctionProperty::TracksLiveness},
.Sets = {},
.Clears = {},
- .RequiredAnalyses = {MachineAnalysisManager::id<LiveVariablesAnalysis>()},
+ .RequiredAnalyses = {MachineFunctionAnalysisManager::id<LiveVariablesAnalysis>()},
.VerificationStage = PipelineStage::RegisterAllocated,
};
Value.ThreadSafety = PassThreadSafety::ThreadSafe;
@@ -120,7 +120,7 @@ const MachinePassContract &MachineFallthroughPass::contract() const noexcept {
Expected<MachinePassResult> MachineFallthroughPass::run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &Analyses) {
+ MachineFunctionAnalysisManager &Analyses) {
if (!Function.properties().containsAll(contract().Requires)) {
return makeUnexpected(ErrorCode::VerificationError,
"fallthrough normalization requires allocated tracked-liveness MIR");
@@ -130,7 +130,7 @@ Expected<MachinePassResult> MachineFallthroughPass::run(MachineFunction &Functio
MachineFunctionCloneOptions{.NewStableID = Function.stableID(), .NewName = std::nullopt});
if (!Trial)
return std::unexpected(prefixedError(Trial.error(), "fallthrough setup failed: "));
- MachineAnalysisManager TrialAnalyses;
+ MachineFunctionAnalysisManager TrialAnalyses;
auto TrialLiveness =
TrialAnalyses.getResult<LiveVariablesAnalysis>(*Trial->ClonedFunction, Target);
if (!TrialLiveness)
diff --git a/backend/lib/CodeGen/MachineFinalization.cpp b/backend/lib/CodeGen/MachineFinalization.cpp
index 8947b86..c33d857 100644
--- a/backend/lib/CodeGen/MachineFinalization.cpp
+++ b/backend/lib/CodeGen/MachineFinalization.cpp
@@ -91,7 +91,7 @@ const MachinePassContract &FinalizeEmissionPseudosPass::contract() const noexcep
Expected<MachinePassResult> FinalizeEmissionPseudosPass::run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &) {
+ MachineFunctionAnalysisManager &) {
if (!Function.properties().containsAll(contract().Requires))
return makeUnexpected(ErrorCode::VerificationError,
"emission-pseudo finalization requires finalized allocated MIR");
@@ -124,7 +124,7 @@ const MachinePassContract &FinalEncodabilityVerifierPass::contract() const noexc
Expected<MachinePassResult> FinalEncodabilityVerifierPass::run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &) {
+ MachineFunctionAnalysisManager &) {
if (!Function.properties().containsAll(contract().Requires))
return makeUnexpected(ErrorCode::FinalEncodabilityFailed,
"final encodability requires NoExecutablePseudos and finalized MIR");
diff --git a/backend/lib/CodeGen/MachineLICM.cpp b/backend/lib/CodeGen/MachineLICM.cpp
index 758e13c..31d792b 100644
--- a/backend/lib/CodeGen/MachineLICM.cpp
+++ b/backend/lib/CodeGen/MachineLICM.cpp
@@ -33,9 +33,9 @@ namespace {
.Requires = {MachineFunctionProperty::IsSSA, MachineFunctionProperty::Selected},
.Sets = {},
.Clears = {},
- .RequiredAnalyses = {MachineAnalysisManager::id<MachineDominatorTreeAnalysis>(),
- MachineAnalysisManager::id<MachineLoopAnalysis>(),
- MachineAnalysisManager::id<MachineBlockFrequencyAnalysis>()},
+ .RequiredAnalyses = {MachineFunctionAnalysisManager::id<MachineDominatorTreeAnalysis>(),
+ MachineFunctionAnalysisManager::id<MachineLoopAnalysis>(),
+ MachineFunctionAnalysisManager::id<MachineBlockFrequencyAnalysis>()},
.VerificationStage = PipelineStage::Selected,
};
Value.ThreadSafety = PassThreadSafety::ThreadSafe;
@@ -50,9 +50,9 @@ namespace {
MachineFunctionProperty::TracksLiveness},
.Sets = {},
.Clears = {},
- .RequiredAnalyses = {MachineAnalysisManager::id<MachineDominatorTreeAnalysis>(),
- MachineAnalysisManager::id<MachineLoopAnalysis>(),
- MachineAnalysisManager::id<MachineBlockFrequencyAnalysis>()},
+ .RequiredAnalyses = {MachineFunctionAnalysisManager::id<MachineDominatorTreeAnalysis>(),
+ MachineFunctionAnalysisManager::id<MachineLoopAnalysis>(),
+ MachineFunctionAnalysisManager::id<MachineBlockFrequencyAnalysis>()},
.VerificationStage = PipelineStage::RegisterAllocated,
};
Value.ThreadSafety = PassThreadSafety::ThreadSafe;
@@ -332,7 +332,7 @@ const MachinePassContract &MachineLICMPass::contract() const noexcept {
Expected<MachinePassResult> MachineLICMPass::run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &Analyses) {
+ MachineFunctionAnalysisManager &Analyses) {
if (!Function.properties().containsAll(contract().Requires)) {
return makeUnexpected(
ErrorCode::VerificationError,
@@ -346,7 +346,7 @@ Expected<MachinePassResult> MachineLICMPass::run(MachineFunction &Function,
if (!Trial) {
return std::unexpected(prefixedError(Trial.error(), "machine LICM transaction setup failed: "));
}
- MachineAnalysisManager TrialAnalyses;
+ MachineFunctionAnalysisManager TrialAnalyses;
auto TrialResult = runImplementation(*Trial->ClonedFunction, Target, TrialAnalyses);
if (!TrialResult)
return std::unexpected(TrialResult.error());
@@ -359,9 +359,9 @@ Expected<MachinePassResult> MachineLICMPass::run(MachineFunction &Function,
return Result;
}
-Expected<MachinePassResult> MachineLICMPass::runImplementation(MachineFunction &Function,
- const TargetDescription &Target,
- MachineAnalysisManager &Analyses) {
+Expected<MachinePassResult>
+MachineLICMPass::runImplementation(MachineFunction &Function, const TargetDescription &Target,
+ MachineFunctionAnalysisManager &Analyses) {
auto Loops = Analyses.getResult<MachineLoopAnalysis>(Function, Target);
if (!Loops)
return std::unexpected(Loops.error());
diff --git a/backend/lib/CodeGen/MachineMemoryFolding.cpp b/backend/lib/CodeGen/MachineMemoryFolding.cpp
index 0e15146..e3d796a 100644
--- a/backend/lib/CodeGen/MachineMemoryFolding.cpp
+++ b/backend/lib/CodeGen/MachineMemoryFolding.cpp
@@ -185,7 +185,7 @@ const MachinePassContract &MachineMemoryFoldingPass::contract() const noexcept {
Expected<MachinePassResult> MachineMemoryFoldingPass::run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &) {
+ MachineFunctionAnalysisManager &) {
if (!Function.properties().containsAll(contract().Requires)) {
return makeUnexpected(ErrorCode::VerificationError,
"memory folding requires selected SSA MachineIR");
diff --git a/backend/lib/CodeGen/MachineOptimizationPipeline.cpp b/backend/lib/CodeGen/MachineOptimizationPipeline.cpp
index 4f116f0..4a9d7f5 100644
--- a/backend/lib/CodeGen/MachineOptimizationPipeline.cpp
+++ b/backend/lib/CodeGen/MachineOptimizationPipeline.cpp
@@ -32,13 +32,13 @@ namespace rcc {
namespace {
template <typename Pass, typename... Arguments>
-[[nodiscard]] Expected<void> addPass(MachinePassManager &Pipeline, Arguments &&...Values) {
+[[nodiscard]] Expected<void> addPass(MachineFunctionPassManager &Pipeline, Arguments &&...Values) {
return Pipeline.addPass(std::make_unique<Pass>(std::forward<Arguments>(Values)...));
}
} // namespace
-Expected<void> registerMachineOptimizationAnalyses(MachineAnalysisManager &Analyses) {
+Expected<void> registerMachineOptimizationAnalyses(MachineFunctionAnalysisManager &Analyses) {
auto Registered = registerStage8MachineAnalyses(Analyses);
if (!Registered)
return std::unexpected(Registered.error());
@@ -46,7 +46,7 @@ Expected<void> registerMachineOptimizationAnalyses(MachineAnalysisManager &Analy
}
Expected<void>
-addSelectedSSAOptimizationPipeline(MachinePassManager &Pipeline,
+addSelectedSSAOptimizationPipeline(MachineFunctionPassManager &Pipeline,
const MachineOptimizationPipelineTargetInfo &TargetInfo) {
auto Added = addPass<MachineCombinerPass>(Pipeline, TargetInfo.Combiner,
MachineCombinerStage::SelectedSSA);
@@ -68,7 +68,7 @@ addSelectedSSAOptimizationPipeline(MachinePassManager &Pipeline,
}
Expected<void> addPreRegisterAllocationOptimizationPipeline(
- MachinePassManager &Pipeline, const MachineOptimizationPipelineTargetInfo &TargetInfo) {
+ MachineFunctionPassManager &Pipeline, const MachineOptimizationPipelineTargetInfo &TargetInfo) {
auto Added = addPass<MachineBranchOptimizationPass>(Pipeline, TargetInfo.InstrInfo);
if (!Added)
return std::unexpected(Added.error());
@@ -87,7 +87,7 @@ Expected<void> addPreRegisterAllocationOptimizationPipeline(
}
Expected<void>
-addPostRegisterAllocationPipeline(MachinePassManager &Pipeline,
+addPostRegisterAllocationPipeline(MachineFunctionPassManager &Pipeline,
const MachineOptimizationPipelineTargetInfo &TargetInfo) {
auto Added = addPass<MachineStackSlotColoringPass>(Pipeline);
if (!Added)
diff --git a/backend/lib/CodeGen/MachinePass.cpp b/backend/lib/CodeGen/MachinePassManager.cpp
index 0ce6f70..0810965 100644
--- a/backend/lib/CodeGen/MachinePass.cpp
+++ b/backend/lib/CodeGen/MachinePassManager.cpp
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-or-later
-#include "rcc/CodeGen/MachinePass.h"
+#include "rcc/CodeGen/MachinePassManager.h"
#include "rcc/CodeGen/CompilationUnit.h"
#include "rcc/CodeGen/MachineBasicBlock.h"
@@ -141,6 +141,56 @@ 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);
@@ -160,7 +210,7 @@ Expected<bool> MachineActionReplay::request(std::string_view Rule, const Machine
const auto Position = RecordingInstructionIDs.find(Instruction);
const MachineInstrStableID CanonicalInstruction =
Position == RecordingInstructionIDs.end() ? Instruction : Position->second;
- auto Accepted = Analyses->requestAction(Rule, Function, CanonicalInstruction, Cost);
+ auto Accepted = Request(Rule, Function, CanonicalInstruction, Cost);
if (!Accepted)
return std::unexpected(Accepted.error());
Decisions.push_back({
@@ -214,452 +264,6 @@ Expected<void> MachineActionReplay::finishReplay() const {
return {};
}
-Expected<void>
-MachineAnalysisManager::registerAnalysisImpl(MachineAnalysisRegistration Registration,
- ErasedRunner Runner, ErasedInvalidator Invalidator) {
- if (Registration.ID == nullptr || Registration.Name.empty() || !Runner || !Invalidator) {
- return makeUnexpected(ErrorCode::InvalidArgument,
- "machine analysis registration is incomplete");
- }
- if (hasDuplicateAnalysisIDs(Registration.Dependencies)) {
- return makeUnexpected(ErrorCode::InvalidArgument,
- "machine analysis dependencies must be non-null and unique");
- }
- if (std::ranges::find(Registration.Dependencies, Registration.ID) !=
- Registration.Dependencies.end()) {
- return makeUnexpected(ErrorCode::InvalidArgument,
- "machine analysis cannot directly depend on itself");
- }
- if (Registry.contains(Registration.ID))
- return makeUnexpected(ErrorCode::InvalidArgument, "machine analysis ID is already registered");
- if (std::ranges::any_of(Registry, [&Registration](const auto &Entry) {
- return Entry.second.Info.Name == Registration.Name;
- })) {
- return makeUnexpected(ErrorCode::InvalidArgument,
- "machine analysis name is already registered");
- }
- const AnalysisID RegistrationID = Registration.ID;
- Registry.emplace(RegistrationID, RegisteredAnalysis{std::move(Registration), std::move(Runner),
- std::move(Invalidator)});
- return {};
-}
-
-bool MachineAnalysisManager::isRegistered(AnalysisID ID) const noexcept {
- return ID != nullptr && Registry.contains(ID);
-}
-
-bool MachineAnalysisManager::hasCached(const MachineFunction &Function,
- AnalysisID ID) const noexcept {
- const auto FunctionPosition = Cache.find(const_cast<MachineFunction *>(&Function));
- if (FunctionPosition == Cache.end())
- return false;
- const auto AnalysisPosition = FunctionPosition->second.find(ID);
- return AnalysisPosition != FunctionPosition->second.end() && AnalysisPosition->second.Value;
-}
-
-std::size_t
-MachineAnalysisManager::cachedResultCount(const MachineFunction &Function) const noexcept {
- const auto Position = Cache.find(const_cast<MachineFunction *>(&Function));
- return Position == Cache.end() ? 0 : Position->second.size();
-}
-
-Expected<void>
-MachineAnalysisManager::materializeDependencies(const RegisteredAnalysis &Registration,
- MachineFunction &Function,
- const TargetDescription &Target) {
- for (const AnalysisID Dependency : Registration.Info.Dependencies) {
- if (!Registry.contains(Dependency)) {
- return makeUnexpected(ErrorCode::InvalidArgument,
- "machine analysis depends on an unregistered analysis");
- }
- auto Result = getResultImpl(Dependency, Function, Target);
- if (!Result)
- return std::unexpected(Result.error());
- }
- return {};
-}
-
-Expected<void *> MachineAnalysisManager::getResultImpl(AnalysisID ID, MachineFunction &Function,
- const TargetDescription &Target) {
- if (ID == nullptr)
- return makeUnexpected(ErrorCode::InvalidArgument, "machine analysis ID cannot be null");
-
- auto &FunctionCache = Cache[&Function];
- if (const auto Cached = FunctionCache.find(ID);
- Cached != FunctionCache.end() && Cached->second.Value) {
- const auto Registration = Registry.find(ID);
- const std::string_view Name = Registration == Registry.end()
- ? std::string_view{"unknown-machine-analysis"}
- : std::string_view{Registration->second.Info.Name};
- if (Instrumentation != nullptr)
- Instrumentation->afterAnalysis(Name, Function, true, 0);
- return Cached->second.Value.get();
- }
-
- const auto RegistrationPosition = Registry.find(ID);
- if (RegistrationPosition == Registry.end())
- return makeUnexpected(ErrorCode::InvalidArgument, "machine analysis ID is not registered");
- const RegisteredAnalysis &Registration = RegistrationPosition->second;
-
- auto &Stack = ActiveComputations[&Function];
- if (std::ranges::find(Stack, ID) != Stack.end()) {
- Error Failure(ErrorCode::InvalidArgument,
- "machine analysis dependency cycle reaches '" + Registration.Info.Name + "'");
- if (Instrumentation != nullptr)
- Instrumentation->analysisFailure(Registration.Info.Name, Function, Failure, 0);
- return std::unexpected(std::move(Failure));
- }
-
- if (Instrumentation != nullptr)
- Instrumentation->beforeAnalysis(Registration.Info.Name, Function);
- const Clock::time_point Start = Clock::now();
- Stack.push_back(ID);
- auto Dependencies = materializeDependencies(Registration, Function, Target);
- if (!Dependencies) {
- Stack.pop_back();
- if (Stack.empty())
- ActiveComputations.erase(&Function);
- Error Failure = prefixedError(Dependencies.error(),
- "machine analysis '" + Registration.Info.Name + "' failed: ");
- if (Instrumentation != nullptr) {
- Instrumentation->analysisFailure(Registration.Info.Name, Function, Failure,
- elapsedNanoseconds(Start));
- }
- return std::unexpected(std::move(Failure));
- }
-
- auto Computed = Registration.Runner(Function, Target, *this);
- Stack.pop_back();
- if (Stack.empty())
- ActiveComputations.erase(&Function);
- const std::uint64_t Duration = elapsedNanoseconds(Start);
- if (!Computed) {
- Error Failure = prefixedError(Computed.error(),
- "machine analysis '" + Registration.Info.Name + "' failed: ");
- if (Instrumentation != nullptr)
- Instrumentation->analysisFailure(Registration.Info.Name, Function, Failure, Duration);
- return std::unexpected(std::move(Failure));
- }
- if (!*Computed) {
- Error Failure(ErrorCode::InternalError,
- "machine analysis '" + Registration.Info.Name + "' returned a null result");
- if (Instrumentation != nullptr)
- Instrumentation->analysisFailure(Registration.Info.Name, Function, Failure, Duration);
- return std::unexpected(std::move(Failure));
- }
-
- void *Result = Computed->get();
- FunctionCache.emplace(ID, CacheEntry{std::move(*Computed), ID});
- if (Instrumentation != nullptr)
- Instrumentation->afterAnalysis(Registration.Info.Name, Function, false, Duration);
- return Result;
-}
-
-void MachineAnalysisManager::invalidate(MachineFunction &Function,
- const PreservedAnalyses &Preserved,
- MachinePassChanges Changes) noexcept {
- const auto FunctionPosition = Cache.find(&Function);
- if (FunctionPosition == Cache.end() || Preserved.preservesAll() || Changes.empty())
- return;
-
- std::set<AnalysisID> Invalid;
- for (auto &[ID, Entry] : FunctionPosition->second) {
- if (Preserved.preserves(ID))
- continue;
- const auto Registration = Registry.find(ID);
- if (Registration == Registry.end() ||
- Registration->second.Info.InvalidatedBy.intersects(Changes)) {
- const bool ShouldInvalidate =
- Registration == Registry.end() || !Entry.Value || !Registration->second.Invalidator ||
- Registration->second.Invalidator(Entry.Value.get(), Function, Preserved);
- if (ShouldInvalidate)
- Invalid.insert(ID);
- }
- }
-
- bool Added = true;
- while (Added) {
- Added = false;
- for (const auto &[ID, Entry] : FunctionPosition->second) {
- (void)Entry;
- if (Invalid.contains(ID) || Preserved.preserves(ID))
- continue;
- const auto Registration = Registry.find(ID);
- if (Registration != Registry.end() &&
- std::ranges::any_of(
- Registration->second.Info.Dependencies,
- [&Invalid](AnalysisID Dependency) { return Invalid.contains(Dependency); })) {
- Added = Invalid.insert(ID).second || Added;
- }
- }
- }
-
- for (const AnalysisID ID : Invalid)
- FunctionPosition->second.erase(ID);
- if (FunctionPosition->second.empty())
- Cache.erase(FunctionPosition);
-}
-
-void MachineAnalysisManager::clear(MachineFunction &Function) noexcept {
- Cache.erase(&Function);
- ActiveComputations.erase(&Function);
-}
-
-void MachineAnalysisManager::clearAll() noexcept {
- Cache.clear();
- ActiveComputations.clear();
-}
-
-Expected<std::unique_ptr<MachineAnalysisManager>> MachineAnalysisManager::forkEmpty() const {
- if (!ActiveComputations.empty()) {
- return makeUnexpected(ErrorCode::InvalidArgument,
- "cannot fork a machine analysis manager during analysis computation");
- }
- auto Result = std::make_unique<MachineAnalysisManager>();
- Result->Registry = Registry;
- return Result;
-}
-
-Expected<void> MachineAnalysisManager::validateParallelRequirements(
- std::span<const AnalysisID> RequiredAnalyses) const {
- std::vector<AnalysisID> Worklist(RequiredAnalyses.begin(), RequiredAnalyses.end());
- std::unordered_set<AnalysisID> Visited;
- for (std::size_t Index = 0; Index < Worklist.size(); ++Index) {
- const AnalysisID ID = Worklist[Index];
- if (ID == nullptr || !Visited.insert(ID).second)
- continue;
- const auto Position = Registry.find(ID);
- if (Position == Registry.end()) {
- return makeUnexpected(ErrorCode::InvalidArgument,
- "parallel machine pass requires an unregistered analysis");
- }
- if (Position->second.Info.ThreadSafety != PassThreadSafety::ThreadSafe) {
- return makeUnexpected(ErrorCode::InvalidArgument,
- "parallel machine pipeline requires analysis '" +
- Position->second.Info.Name + "' to be marked thread-safe");
- }
- Worklist.insert(Worklist.end(), Position->second.Info.Dependencies.begin(),
- Position->second.Info.Dependencies.end());
- }
- return {};
-}
-
-Expected<bool> MachineAnalysisManager::requestAction(std::string_view Action,
- const MachineFunction &Function,
- std::uint64_t Cost) {
- return requestAction(Action, Function, MachineInstrStableID{}, Cost);
-}
-
-Expected<bool> MachineAnalysisManager::requestAction(std::string_view Rule,
- const MachineFunction &Function,
- MachineInstrStableID Instruction,
- std::uint64_t Cost) {
- if (Rule.empty() || Cost == 0)
- return makeUnexpected(ErrorCode::InvalidArgument,
- "machine action requires a name and nonzero cost");
- if (Instrumentation == nullptr)
- return true;
- MachineActionID ID{
- .Pass = ActivePass.empty() ? "unscoped" : ActivePass,
- .Rule = std::string(Rule),
- .Function = Function.stableID(),
- .Instruction = Instruction,
- };
- return Instrumentation->requestAction(ID, Function, Cost);
-}
-
-Expected<void> CompilationUnitAnalysisManager::registerAnalysisImpl(
- CompilationUnitAnalysisRegistration Registration, ErasedRunner Runner,
- ErasedInvalidator Invalidator) {
- if (Registration.ID == nullptr || Registration.Name.empty() || !Runner || !Invalidator) {
- return makeUnexpected(ErrorCode::InvalidArgument,
- "compilation-unit analysis registration is incomplete");
- }
- if (hasDuplicateAnalysisIDs(Registration.Dependencies)) {
- return makeUnexpected(ErrorCode::InvalidArgument,
- "compilation-unit analysis dependencies must be non-null and unique");
- }
- if (std::ranges::find(Registration.Dependencies, Registration.ID) !=
- Registration.Dependencies.end()) {
- return makeUnexpected(ErrorCode::InvalidArgument,
- "compilation-unit analysis cannot directly depend on itself");
- }
- if (Registry.contains(Registration.ID)) {
- return makeUnexpected(ErrorCode::InvalidArgument,
- "compilation-unit analysis ID is already registered");
- }
- if (std::ranges::any_of(Registry, [&Registration](const auto &Entry) {
- return Entry.second.Info.Name == Registration.Name;
- })) {
- return makeUnexpected(ErrorCode::InvalidArgument,
- "compilation-unit analysis name is already registered");
- }
- const AnalysisID RegistrationID = Registration.ID;
- Registry.emplace(RegistrationID, RegisteredAnalysis{std::move(Registration), std::move(Runner),
- std::move(Invalidator)});
- return {};
-}
-
-bool CompilationUnitAnalysisManager::isRegistered(AnalysisID ID) const noexcept {
- return ID != nullptr && Registry.contains(ID);
-}
-
-bool CompilationUnitAnalysisManager::hasCached(const CompilationUnit &Unit,
- AnalysisID ID) const noexcept {
- const auto UnitPosition = Cache.find(const_cast<CompilationUnit *>(&Unit));
- if (UnitPosition == Cache.end())
- return false;
- const auto AnalysisPosition = UnitPosition->second.find(ID);
- return AnalysisPosition != UnitPosition->second.end() && AnalysisPosition->second.Value;
-}
-
-Expected<void>
-CompilationUnitAnalysisManager::materializeDependencies(const RegisteredAnalysis &Registration,
- CompilationUnit &Unit,
- const TargetDescription &Target) {
- for (const AnalysisID Dependency : Registration.Info.Dependencies) {
- if (!Registry.contains(Dependency)) {
- return makeUnexpected(ErrorCode::InvalidArgument,
- "compilation-unit analysis depends on an unregistered analysis");
- }
- auto Result = getResultImpl(Dependency, Unit, Target);
- if (!Result)
- return std::unexpected(Result.error());
- }
- return {};
-}
-
-Expected<void *> CompilationUnitAnalysisManager::getResultImpl(AnalysisID ID, CompilationUnit &Unit,
- const TargetDescription &Target) {
- if (ID == nullptr)
- return makeUnexpected(ErrorCode::InvalidArgument,
- "compilation-unit analysis ID cannot be null");
- auto &UnitCache = Cache[&Unit];
- if (const auto Cached = UnitCache.find(ID); Cached != UnitCache.end() && Cached->second.Value) {
- const auto Registration = Registry.find(ID);
- const std::string_view Name = Registration == Registry.end()
- ? std::string_view{"unknown-compilation-unit-analysis"}
- : std::string_view{Registration->second.Info.Name};
- if (Instrumentation != nullptr)
- Instrumentation->afterUnitAnalysis(Name, Unit, true, 0);
- return Cached->second.Value.get();
- }
-
- const auto RegistrationPosition = Registry.find(ID);
- if (RegistrationPosition == Registry.end()) {
- return makeUnexpected(ErrorCode::InvalidArgument,
- "compilation-unit analysis ID is not registered");
- }
- const RegisteredAnalysis &Registration = RegistrationPosition->second;
- auto &Stack = ActiveComputations[&Unit];
- if (std::ranges::find(Stack, ID) != Stack.end()) {
- Error Failure(ErrorCode::InvalidArgument,
- "compilation-unit analysis dependency cycle reaches '" + Registration.Info.Name +
- "'");
- if (Instrumentation != nullptr)
- Instrumentation->unitAnalysisFailure(Registration.Info.Name, Unit, Failure, 0);
- return std::unexpected(std::move(Failure));
- }
-
- if (Instrumentation != nullptr)
- Instrumentation->beforeUnitAnalysis(Registration.Info.Name, Unit);
- const Clock::time_point Start = Clock::now();
- Stack.push_back(ID);
- auto Dependencies = materializeDependencies(Registration, Unit, Target);
- if (!Dependencies) {
- Stack.pop_back();
- if (Stack.empty())
- ActiveComputations.erase(&Unit);
- Error Failure = prefixedError(Dependencies.error(), "compilation-unit analysis '" +
- Registration.Info.Name + "' failed: ");
- if (Instrumentation != nullptr) {
- Instrumentation->unitAnalysisFailure(Registration.Info.Name, Unit, Failure,
- elapsedNanoseconds(Start));
- }
- return std::unexpected(std::move(Failure));
- }
-
- auto Computed = Registration.Runner(Unit, Target, *this);
- Stack.pop_back();
- if (Stack.empty())
- ActiveComputations.erase(&Unit);
- const std::uint64_t Duration = elapsedNanoseconds(Start);
- if (!Computed) {
- Error Failure = prefixedError(Computed.error(), "compilation-unit analysis '" +
- Registration.Info.Name + "' failed: ");
- if (Instrumentation != nullptr)
- Instrumentation->unitAnalysisFailure(Registration.Info.Name, Unit, Failure, Duration);
- return std::unexpected(std::move(Failure));
- }
- if (!*Computed) {
- Error Failure(ErrorCode::InternalError, "compilation-unit analysis '" + Registration.Info.Name +
- "' returned a null result");
- if (Instrumentation != nullptr)
- Instrumentation->unitAnalysisFailure(Registration.Info.Name, Unit, Failure, Duration);
- return std::unexpected(std::move(Failure));
- }
-
- void *Result = Computed->get();
- UnitCache.emplace(ID, CacheEntry{std::move(*Computed), ID});
- if (Instrumentation != nullptr)
- Instrumentation->afterUnitAnalysis(Registration.Info.Name, Unit, false, Duration);
- return Result;
-}
-
-void CompilationUnitAnalysisManager::invalidate(CompilationUnit &Unit,
- const PreservedAnalyses &Preserved,
- MachinePassChanges Changes) noexcept {
- const auto UnitPosition = Cache.find(&Unit);
- if (UnitPosition == Cache.end() || Preserved.preservesAll() || Changes.empty())
- return;
-
- std::set<AnalysisID> Invalid;
- for (auto &[ID, Entry] : UnitPosition->second) {
- if (Preserved.preserves(ID))
- continue;
- const auto Registration = Registry.find(ID);
- if (Registration == Registry.end() ||
- Registration->second.Info.InvalidatedBy.intersects(Changes)) {
- const bool ShouldInvalidate =
- Registration == Registry.end() || !Entry.Value || !Registration->second.Invalidator ||
- Registration->second.Invalidator(Entry.Value.get(), Unit, Preserved);
- if (ShouldInvalidate)
- Invalid.insert(ID);
- }
- }
-
- bool Added = true;
- while (Added) {
- Added = false;
- for (const auto &[ID, Entry] : UnitPosition->second) {
- (void)Entry;
- if (Invalid.contains(ID) || Preserved.preserves(ID))
- continue;
- const auto Registration = Registry.find(ID);
- if (Registration != Registry.end() &&
- std::ranges::any_of(
- Registration->second.Info.Dependencies,
- [&Invalid](AnalysisID Dependency) { return Invalid.contains(Dependency); })) {
- Added = Invalid.insert(ID).second || Added;
- }
- }
- }
- for (const AnalysisID InvalidID : Invalid)
- UnitPosition->second.erase(InvalidID);
- if (UnitPosition->second.empty())
- Cache.erase(UnitPosition);
-}
-
-void CompilationUnitAnalysisManager::clear(CompilationUnit &Unit) noexcept {
- Cache.erase(&Unit);
- ActiveComputations.erase(&Unit);
-}
-
-void CompilationUnitAnalysisManager::clearAll() noexcept {
- Cache.clear();
- ActiveComputations.clear();
-}
-
void MachinePassInstrumentation::addBeforeCallback(BeforeCallback Callback) {
if (!Callback)
return;
@@ -966,9 +570,17 @@ void MachinePassInstrumentation::change(std::string_view Name, const MachineFunc
Callback(Name, Function, Changes, FingerprintChanged);
}
-Expected<bool> MachinePassInstrumentation::requestAction(const MachineActionID &Action,
+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");
@@ -1000,6 +612,13 @@ Expected<bool> MachinePassInstrumentation::requestAction(const MachineActionID &
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;
@@ -1043,8 +662,8 @@ void MachinePassInstrumentation::unitFailure(std::string_view Name, const Compil
Callback(Name, Unit, ErrorValue);
}
-void MachinePassInstrumentation::beforeUnitAnalysis(std::string_view Name,
- const CompilationUnit &Unit) const {
+void MachinePassInstrumentation::beforeAnalysis(std::string_view Name,
+ const CompilationUnit &Unit) const {
std::vector<BeforeUnitAnalysisCallback> Callbacks;
{
std::scoped_lock Lock(Mutex);
@@ -1054,9 +673,8 @@ void MachinePassInstrumentation::beforeUnitAnalysis(std::string_view Name,
Callback(Name, Unit);
}
-void MachinePassInstrumentation::afterUnitAnalysis(std::string_view Name,
- const CompilationUnit &Unit, bool CacheHit,
- std::uint64_t Nanoseconds) const {
+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);
@@ -1070,10 +688,9 @@ void MachinePassInstrumentation::afterUnitAnalysis(std::string_view Name,
Callback(Name, Unit, CacheHit, Nanoseconds);
}
-void MachinePassInstrumentation::unitAnalysisFailure(std::string_view Name,
- const CompilationUnit &Unit,
- const Error &ErrorValue,
- std::uint64_t Nanoseconds) const {
+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);
@@ -1128,14 +745,10 @@ std::vector<MachineActionEvent> MachinePassInstrumentation::actionEvents() const
return Result;
}
-void MachinePassInstrumentation::clearStatistics() {
- std::scoped_lock Lock(Mutex);
- Statistics.clear();
- ConsumedFuel.clear();
- ActionEvents.clear();
-}
-
-Expected<void> MachinePassManager::validateContract(const MachinePassContract &Contract) const {
+Expected<void>
+PassManagerCallbacks<MachineFunction, MachineFunctionPass, MachinePassManagerOptions>::validate(
+ const MachineFunctionPass &Pass) {
+ const MachinePassContract &Contract = Pass.contract();
if (Contract.Name.empty())
return makeUnexpected(ErrorCode::InvalidArgument, "machine pass must have a non-empty name");
if (Contract.Sets.intersects(Contract.Clears)) {
@@ -1149,20 +762,11 @@ Expected<void> MachinePassManager::validateContract(const MachinePassContract &C
return validateParameters(Contract.Parameters);
}
-Expected<void> MachinePassManager::addPass(std::unique_ptr<MachineFunctionPass> Pass) {
- if (!Pass)
- return makeUnexpected(ErrorCode::InvalidArgument,
- "machine pass manager cannot add a null pass");
- auto Validation = validateContract(Pass->contract());
- if (!Validation)
- return std::unexpected(Validation.error());
- Passes.push_back(std::move(Pass));
- return {};
-}
-
-Expected<void> MachinePassManager::run(MachineFunction &Function, const TargetDescription &Target,
- MachineAnalysisManager &Analyses,
- MachinePassInstrumentation *Instrumentation) const {
+Expected<void>
+PassManagerCallbacks<MachineFunction, MachineFunctionPass, MachinePassManagerOptions>::run(
+ const PassList &Passes, const MachinePassManagerOptions &Options, MachineFunction &Function,
+ const TargetDescription &Target, MachineFunctionAnalysisManager &Analyses,
+ MachinePassInstrumentation *Instrumentation) {
Analyses.setInstrumentation(Instrumentation);
for (const std::unique_ptr<MachineFunctionPass> &Pass : Passes) {
const MachinePassContract &Contract = Pass->contract();
@@ -1192,7 +796,7 @@ Expected<void> MachinePassManager::run(MachineFunction &Function, const TargetDe
}
for (const AnalysisID Required : Contract.RequiredAnalyses) {
- auto Result = Analyses.getResultImpl(Required, Function, Target);
+ auto Result = Analyses.getResultByID(Required, Function, Target);
if (!Result) {
Error Failure =
prefixedError(Result.error(), "pass '" + std::string(Name) +
@@ -1209,9 +813,9 @@ Expected<void> MachinePassManager::run(MachineFunction &Function, const TargetDe
if (Instrumentation != nullptr)
Instrumentation->before(Name, Function);
const Clock::time_point Start = Clock::now();
- Analyses.ActivePass = std::string(Name);
+ Analyses.setActivePass(std::string(Name));
auto PassResult = Pass->run(Function, Target, Analyses);
- Analyses.ActivePass.clear();
+ Analyses.setActivePass({});
const std::uint64_t Duration = elapsedNanoseconds(Start);
if (!PassResult) {
Error Failure =
@@ -1296,11 +900,11 @@ Expected<void> MachinePassManager::run(MachineFunction &Function, const TargetDe
return {};
}
-Expected<void> MachinePassManager::runFunctions(CompilationUnit &Unit,
- const TargetDescription &Target,
- const MachineAnalysisManager &AnalysisPrototype,
- std::size_t ThreadCount,
- MachinePassInstrumentation *Instrumentation) const {
+Expected<void>
+PassManagerCallbacks<MachineFunction, MachineFunctionPass, MachinePassManagerOptions>::runFunctions(
+ const PassList &Passes, const MachinePassManagerOptions &Options, CompilationUnit &Unit,
+ const TargetDescription &Target, const MachineFunctionAnalysisManager &AnalysisPrototype,
+ std::size_t ThreadCount, MachinePassInstrumentation *Instrumentation) {
if (ThreadCount == 0)
return makeUnexpected(ErrorCode::InvalidArgument, "machine pass thread count must be nonzero");
auto UnitVerification = verifyCompilationUnit(Unit, Target);
@@ -1322,7 +926,7 @@ Expected<void> MachinePassManager::runFunctions(CompilationUnit &Unit,
return std::unexpected(AnalysisSafety.error());
}
}
- std::vector<std::unique_ptr<MachineAnalysisManager>> Managers;
+ std::vector<std::unique_ptr<MachineFunctionAnalysisManager>> Managers;
Managers.reserve(FunctionCount);
for (std::size_t Index = 0; Index < FunctionCount; ++Index) {
auto Manager = AnalysisPrototype.forkEmpty();
@@ -1347,7 +951,8 @@ Expected<void> MachinePassManager::runFunctions(CompilationUnit &Unit,
}
if (Instrumentation != nullptr)
Instrumentation->beginBuffering(EventBuffers[Index], Target);
- auto Result = run(*Function, Target, *Managers[Index], Instrumentation);
+ auto Result = PassManagerCallbacks::run(Passes, Options, *Function, Target, *Managers[Index],
+ Instrumentation);
if (Instrumentation != nullptr)
Instrumentation->endBuffering();
if (!Result)
@@ -1374,12 +979,10 @@ Expected<void> MachinePassManager::runFunctions(CompilationUnit &Unit,
return {};
}
-Expected<void> CompilationUnitPassManager::addPass(std::unique_ptr<CompilationUnitPass> Pass) {
- if (!Pass) {
- return makeUnexpected(ErrorCode::InvalidArgument,
- "compilation-unit pass manager cannot add a null pass");
- }
- const CompilationUnitPassContract &Contract = Pass->contract();
+Expected<void>
+PassManagerCallbacks<CompilationUnit, CompilationUnitPass,
+ CompilationUnitPassManagerOptions>::validate(const CompilationUnitPass &Pass) {
+ const CompilationUnitPassContract &Contract = Pass.contract();
if (Contract.Name.empty()) {
return makeUnexpected(ErrorCode::InvalidArgument,
"compilation-unit pass must have a non-empty name");
@@ -1391,15 +994,14 @@ Expected<void> CompilationUnitPassManager::addPass(std::unique_ptr<CompilationUn
auto Parameters = validateParameters(Contract.Parameters);
if (!Parameters)
return std::unexpected(Parameters.error());
- Passes.push_back(std::move(Pass));
return {};
}
-Expected<void> CompilationUnitPassManager::run(CompilationUnit &Unit,
- const TargetDescription &Target,
- CompilationUnitAnalysisManager &UnitAnalyses,
- MachineAnalysisManager &FunctionAnalyses,
- MachinePassInstrumentation *Instrumentation) const {
+Expected<void>
+PassManagerCallbacks<CompilationUnit, CompilationUnitPass, CompilationUnitPassManagerOptions>::run(
+ const PassList &Passes, const CompilationUnitPassManagerOptions &Options, CompilationUnit &Unit,
+ const TargetDescription &Target, CompilationUnitAnalysisManager &UnitAnalyses,
+ MachineFunctionAnalysisManager &FunctionAnalyses, MachinePassInstrumentation *Instrumentation) {
UnitAnalyses.setInstrumentation(Instrumentation);
FunctionAnalyses.setInstrumentation(Instrumentation);
for (const std::unique_ptr<CompilationUnitPass> &Pass : Passes) {
@@ -1421,7 +1023,7 @@ Expected<void> CompilationUnitPassManager::run(CompilationUnit &Unit,
}
for (const AnalysisID Required : Contract.RequiredAnalyses) {
- auto Result = UnitAnalyses.getResultImpl(Required, Unit, Target);
+ auto Result = UnitAnalyses.getResultByID(Required, Unit, Target);
if (!Result) {
Error Failure =
prefixedError(Result.error(), "compilation-unit pass '" + std::string(Name) +
diff --git a/backend/lib/CodeGen/MachinePseudoExpansion.cpp b/backend/lib/CodeGen/MachinePseudoExpansion.cpp
index b5afe8e..663b148 100644
--- a/backend/lib/CodeGen/MachinePseudoExpansion.cpp
+++ b/backend/lib/CodeGen/MachinePseudoExpansion.cpp
@@ -355,7 +355,8 @@ expandImplementation(MachineFunction &Function, const TargetDescription &Target,
[[nodiscard]] Expected<MachinePassResult>
runPreparationTransaction(MachineFunction &Function, const TargetDescription &Target,
- const TargetPseudoExpansionInfo &Info, MachineAnalysisManager &Analyses) {
+ const TargetPseudoExpansionInfo &Info,
+ MachineFunctionAnalysisManager &Analyses) {
auto Trial = cloneMachineFunction(
Function, Target,
MachineFunctionCloneOptions{.NewStableID = Function.stableID(), .NewName = std::nullopt});
@@ -380,7 +381,8 @@ runPreparationTransaction(MachineFunction &Function, const TargetDescription &Ta
[[nodiscard]] Expected<MachinePassResult>
runExpansionTransaction(MachineFunction &Function, const TargetDescription &Target,
const TargetPseudoExpansionInfo &Info, MachinePseudoExpansionPhase Phase,
- const TargetInstrInfo *BranchInfo, MachineAnalysisManager &Analyses) {
+ const TargetInstrInfo *BranchInfo,
+ MachineFunctionAnalysisManager &Analyses) {
auto Trial = cloneMachineFunction(
Function, Target,
MachineFunctionCloneOptions{.NewStableID = Function.stableID(), .NewName = std::nullopt});
@@ -409,9 +411,9 @@ const MachinePassContract &PreparePostRAPseudosPass::contract() const noexcept {
return preparationContract();
}
-Expected<MachinePassResult> PreparePostRAPseudosPass::run(MachineFunction &Function,
- const TargetDescription &Target,
- MachineAnalysisManager &Analyses) {
+Expected<MachinePassResult>
+PreparePostRAPseudosPass::run(MachineFunction &Function, const TargetDescription &Target,
+ MachineFunctionAnalysisManager &Analyses) {
if (!Function.properties().containsAll(contract().Requires))
return makeUnexpected(ErrorCode::VerificationError,
"post-RA pseudo preparation requires selected MachineIR");
@@ -422,9 +424,9 @@ const MachinePassContract &PrePEITargetPseudoExpansionPass::contract() const noe
return phaseContract(MachinePseudoExpansionPhase::PrePEI);
}
-Expected<MachinePassResult> PrePEITargetPseudoExpansionPass::run(MachineFunction &Function,
- const TargetDescription &Target,
- MachineAnalysisManager &Analyses) {
+Expected<MachinePassResult>
+PrePEITargetPseudoExpansionPass::run(MachineFunction &Function, const TargetDescription &Target,
+ MachineFunctionAnalysisManager &Analyses) {
if (!Function.properties().containsAll(contract().Requires))
return makeUnexpected(ErrorCode::VerificationError,
"pre-PEI pseudo expansion requires allocated tracked-liveness MIR");
@@ -438,7 +440,7 @@ const MachinePassContract &ExpandPostRAPseudosPass::contract() const noexcept {
Expected<MachinePassResult> ExpandPostRAPseudosPass::run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &Analyses) {
+ MachineFunctionAnalysisManager &Analyses) {
if (!Function.properties().containsAll(contract().Requires))
return makeUnexpected(ErrorCode::VerificationError,
"post-RA pseudo expansion requires finalized frame and liveness");
@@ -450,9 +452,9 @@ const MachinePassContract &TargetLatePseudoExpansionPass::contract() const noexc
return phaseContract(MachinePseudoExpansionPhase::TargetLate);
}
-Expected<MachinePassResult> TargetLatePseudoExpansionPass::run(MachineFunction &Function,
- const TargetDescription &Target,
- MachineAnalysisManager &Analyses) {
+Expected<MachinePassResult>
+TargetLatePseudoExpansionPass::run(MachineFunction &Function, const TargetDescription &Target,
+ MachineFunctionAnalysisManager &Analyses) {
if (!Function.properties().containsAll(contract().Requires))
return makeUnexpected(ErrorCode::VerificationError,
"target-late pseudo expansion requires finalized allocated MIR");
diff --git a/backend/lib/CodeGen/MachineScheduler.cpp b/backend/lib/CodeGen/MachineScheduler.cpp
index e589675..82f0c91 100644
--- a/backend/lib/CodeGen/MachineScheduler.cpp
+++ b/backend/lib/CodeGen/MachineScheduler.cpp
@@ -37,10 +37,11 @@ namespace {
MachineFunctionProperty::TiedOpsRewritten},
.Sets = {},
.Clears = {},
- .RequiredAnalyses = {MachineAnalysisManager::id<LiveVariablesAnalysis>()},
+ .RequiredAnalyses = {MachineFunctionAnalysisManager::id<LiveVariablesAnalysis>()},
.VerificationStage = PipelineStage::TiedOpsRewritten,
};
- Value.RequiredAnalyses.push_back(MachineAnalysisManager::id<MachineBlockFrequencyAnalysis>());
+ Value.RequiredAnalyses.push_back(
+ MachineFunctionAnalysisManager::id<MachineBlockFrequencyAnalysis>());
Value.ThreadSafety = PassThreadSafety::ThreadSafe;
Value.DeclaredChanges = {MachinePassChange::Instructions, MachinePassChange::Operands};
return Value;
@@ -395,7 +396,7 @@ const MachinePassContract &MachineSchedulerPass::contract() const noexcept {
Expected<MachinePassResult> MachineSchedulerPass::run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &Analyses) {
+ MachineFunctionAnalysisManager &Analyses) {
if (!Function.properties().containsAll(contract().Requires)) {
return makeUnexpected(ErrorCode::VerificationError,
"pre-RA machine scheduler requires selected, SSA-exited MachineIR");
@@ -407,7 +408,7 @@ Expected<MachinePassResult> MachineSchedulerPass::run(MachineFunction &Function,
return std::unexpected(
prefixedError(Trial.error(), "machine scheduler transaction setup failed: "));
}
- MachineAnalysisManager TrialAnalyses;
+ MachineFunctionAnalysisManager TrialAnalyses;
auto TrialLiveness =
TrialAnalyses.getResult<LiveVariablesAnalysis>(*Trial->ClonedFunction, Target);
if (!TrialLiveness)
diff --git a/backend/lib/CodeGen/MachineShrinkWrapping.cpp b/backend/lib/CodeGen/MachineShrinkWrapping.cpp
index aee3323..7c7bc3a 100644
--- a/backend/lib/CodeGen/MachineShrinkWrapping.cpp
+++ b/backend/lib/CodeGen/MachineShrinkWrapping.cpp
@@ -32,8 +32,8 @@ namespace {
MachineFunctionProperty::TracksLiveness},
.Sets = {},
.Clears = {},
- .RequiredAnalyses = {MachineAnalysisManager::id<MachineDominatorTreeAnalysis>(),
- MachineAnalysisManager::id<MachineLoopAnalysis>()},
+ .RequiredAnalyses = {MachineFunctionAnalysisManager::id<MachineDominatorTreeAnalysis>(),
+ MachineFunctionAnalysisManager::id<MachineLoopAnalysis>()},
.VerificationStage = PipelineStage::RegisterAllocated,
};
Value.ThreadSafety = PassThreadSafety::ThreadSafe;
@@ -66,9 +66,9 @@ const MachinePassContract &MachineShrinkWrappingPass::contract() const noexcept
return shrinkWrappingContract();
}
-Expected<MachinePassResult> MachineShrinkWrappingPass::run(MachineFunction &Function,
- const TargetDescription &Target,
- MachineAnalysisManager &Analyses) {
+Expected<MachinePassResult>
+MachineShrinkWrappingPass::run(MachineFunction &Function, const TargetDescription &Target,
+ MachineFunctionAnalysisManager &Analyses) {
if (!Function.properties().containsAll(contract().Requires)) {
return makeUnexpected(ErrorCode::VerificationError,
"shrink wrapping requires allocated tracked-liveness MachineIR");
diff --git a/backend/lib/CodeGen/MachineSink.cpp b/backend/lib/CodeGen/MachineSink.cpp
index 21b17f8..176b75a 100644
--- a/backend/lib/CodeGen/MachineSink.cpp
+++ b/backend/lib/CodeGen/MachineSink.cpp
@@ -34,8 +34,8 @@ namespace {
.Requires = {MachineFunctionProperty::IsSSA, MachineFunctionProperty::Selected},
.Sets = {},
.Clears = {},
- .RequiredAnalyses = {MachineAnalysisManager::id<MachineDominatorTreeAnalysis>(),
- MachineAnalysisManager::id<MachineBlockFrequencyAnalysis>()},
+ .RequiredAnalyses = {MachineFunctionAnalysisManager::id<MachineDominatorTreeAnalysis>(),
+ MachineFunctionAnalysisManager::id<MachineBlockFrequencyAnalysis>()},
.VerificationStage = PipelineStage::Selected,
};
Value.ThreadSafety = PassThreadSafety::ThreadSafe;
@@ -50,8 +50,8 @@ namespace {
MachineFunctionProperty::TracksLiveness},
.Sets = {},
.Clears = {},
- .RequiredAnalyses = {MachineAnalysisManager::id<MachineDominatorTreeAnalysis>(),
- MachineAnalysisManager::id<MachineBlockFrequencyAnalysis>()},
+ .RequiredAnalyses = {MachineFunctionAnalysisManager::id<MachineDominatorTreeAnalysis>(),
+ MachineFunctionAnalysisManager::id<MachineBlockFrequencyAnalysis>()},
.VerificationStage = PipelineStage::RegisterAllocated,
};
Value.ThreadSafety = PassThreadSafety::ThreadSafe;
@@ -354,7 +354,7 @@ const MachinePassContract &MachineSinkPass::contract() const noexcept {
Expected<MachinePassResult> MachineSinkPass::run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &Analyses) {
+ MachineFunctionAnalysisManager &Analyses) {
if (!Function.properties().containsAll(contract().Requires)) {
return makeUnexpected(
ErrorCode::VerificationError,
@@ -368,7 +368,7 @@ Expected<MachinePassResult> MachineSinkPass::run(MachineFunction &Function,
if (!Trial) {
return std::unexpected(prefixedError(Trial.error(), "machine sink transaction setup failed: "));
}
- MachineAnalysisManager TrialAnalyses;
+ MachineFunctionAnalysisManager TrialAnalyses;
auto TrialResult = runImplementation(*Trial->ClonedFunction, Target, TrialAnalyses);
if (!TrialResult)
return std::unexpected(TrialResult.error());
@@ -381,9 +381,9 @@ Expected<MachinePassResult> MachineSinkPass::run(MachineFunction &Function,
return Result;
}
-Expected<MachinePassResult> MachineSinkPass::runImplementation(MachineFunction &Function,
- const TargetDescription &Target,
- MachineAnalysisManager &Analyses) {
+Expected<MachinePassResult>
+MachineSinkPass::runImplementation(MachineFunction &Function, const TargetDescription &Target,
+ MachineFunctionAnalysisManager &Analyses) {
auto Dominators = Analyses.getResult<MachineDominatorTreeAnalysis>(Function, Target);
if (!Dominators)
return std::unexpected(Dominators.error());
diff --git a/backend/lib/CodeGen/MachineStackSlotColoring.cpp b/backend/lib/CodeGen/MachineStackSlotColoring.cpp
index e60a7a2..005872b 100644
--- a/backend/lib/CodeGen/MachineStackSlotColoring.cpp
+++ b/backend/lib/CodeGen/MachineStackSlotColoring.cpp
@@ -228,7 +228,7 @@ const MachinePassContract &MachineStackSlotColoringPass::contract() const noexce
Expected<MachinePassResult> MachineStackSlotColoringPass::run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &) {
+ MachineFunctionAnalysisManager &) {
if (!Function.properties().containsAll(contract().Requires)) {
return makeUnexpected(ErrorCode::VerificationError,
"stack-slot coloring requires allocated PHI-free MachineIR");
diff --git a/backend/lib/CodeGen/MachineTailDuplication.cpp b/backend/lib/CodeGen/MachineTailDuplication.cpp
index 5abd473..8be1eb5 100644
--- a/backend/lib/CodeGen/MachineTailDuplication.cpp
+++ b/backend/lib/CodeGen/MachineTailDuplication.cpp
@@ -248,7 +248,7 @@ const MachinePassContract &MachineTailDuplicationPass::contract() const noexcept
Expected<MachinePassResult> MachineTailDuplicationPass::run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &) {
+ MachineFunctionAnalysisManager &) {
if (!Function.properties().containsAll(contract().Requires)) {
return makeUnexpected(ErrorCode::VerificationError,
"tail duplication requires finalized allocated tracked-liveness MIR");
diff --git a/backend/lib/CodeGen/MachineTailMerge.cpp b/backend/lib/CodeGen/MachineTailMerge.cpp
index c4d6de9..dc07950 100644
--- a/backend/lib/CodeGen/MachineTailMerge.cpp
+++ b/backend/lib/CodeGen/MachineTailMerge.cpp
@@ -298,7 +298,7 @@ const MachinePassContract &MachineTailMergePass::contract() const noexcept {
Expected<MachinePassResult> MachineTailMergePass::run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &) {
+ MachineFunctionAnalysisManager &) {
if (!Function.properties().containsAll(contract().Requires)) {
return makeUnexpected(ErrorCode::VerificationError,
"tail merge requires finalized allocated tracked-liveness MIR");
diff --git a/backend/lib/CodeGen/PHIElimination.cpp b/backend/lib/CodeGen/PHIElimination.cpp
index 75472f2..6de449f 100644
--- a/backend/lib/CodeGen/PHIElimination.cpp
+++ b/backend/lib/CodeGen/PHIElimination.cpp
@@ -490,7 +490,7 @@ const MachinePassContract &PHIEliminationPass::contract() const noexcept {
Expected<MachinePassResult> PHIEliminationPass::run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &Analyses) {
+ MachineFunctionAnalysisManager &Analyses) {
auto Required = requireProperties(Function, contract());
if (!Required)
return std::unexpected(Required.error());
diff --git a/backend/lib/CodeGen/PostRAScheduler.cpp b/backend/lib/CodeGen/PostRAScheduler.cpp
index f7d6181..b5f7ae9 100644
--- a/backend/lib/CodeGen/PostRAScheduler.cpp
+++ b/backend/lib/CodeGen/PostRAScheduler.cpp
@@ -37,10 +37,11 @@ namespace {
MachineFunctionProperty::TracksLiveness},
.Sets = {},
.Clears = {},
- .RequiredAnalyses = {MachineAnalysisManager::id<LiveVariablesAnalysis>()},
+ .RequiredAnalyses = {MachineFunctionAnalysisManager::id<LiveVariablesAnalysis>()},
.VerificationStage = PipelineStage::RegisterAllocated,
};
- Value.RequiredAnalyses.push_back(MachineAnalysisManager::id<MachineBlockFrequencyAnalysis>());
+ Value.RequiredAnalyses.push_back(
+ MachineFunctionAnalysisManager::id<MachineBlockFrequencyAnalysis>());
Value.ThreadSafety = PassThreadSafety::ThreadSafe;
Value.DeclaredChanges = {MachinePassChange::Instructions, MachinePassChange::Operands};
return Value;
@@ -61,7 +62,7 @@ const MachinePassContract &PostRASchedulerPass::contract() const noexcept {
Expected<MachinePassResult> PostRASchedulerPass::run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &Analyses) {
+ MachineFunctionAnalysisManager &Analyses) {
if (!Function.properties().containsAll(contract().Requires)) {
return makeUnexpected(ErrorCode::VerificationError,
"post-RA scheduler requires allocated tracked-liveness MachineIR");
@@ -73,7 +74,7 @@ Expected<MachinePassResult> PostRASchedulerPass::run(MachineFunction &Function,
return std::unexpected(
prefixedError(Trial.error(), "post-RA scheduler transaction setup failed: "));
}
- MachineAnalysisManager TrialAnalyses;
+ MachineFunctionAnalysisManager TrialAnalyses;
auto TrialLiveness =
TrialAnalyses.getResult<LiveVariablesAnalysis>(*Trial->ClonedFunction, Target);
if (!TrialLiveness)
diff --git a/backend/lib/CodeGen/PrologueEpilogueInsertion.cpp b/backend/lib/CodeGen/PrologueEpilogueInsertion.cpp
index 47b74f6..c935d6a 100644
--- a/backend/lib/CodeGen/PrologueEpilogueInsertion.cpp
+++ b/backend/lib/CodeGen/PrologueEpilogueInsertion.cpp
@@ -49,7 +49,7 @@ const MachinePassContract &PrologueEpilogueInsertionPass::contract() const noexc
Expected<MachinePassResult> PrologueEpilogueInsertionPass::run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &) {
+ MachineFunctionAnalysisManager &) {
if (Info == nullptr)
return makeUnexpected(ErrorCode::InvalidArgument,
"PrologueEpilogueInsertion requires target frame lowering");
diff --git a/backend/lib/CodeGen/RegAllocBase.h b/backend/lib/CodeGen/RegAllocBase.h
index 318a82d..4ef0bb7 100644
--- a/backend/lib/CodeGen/RegAllocBase.h
+++ b/backend/lib/CodeGen/RegAllocBase.h
@@ -27,8 +27,9 @@ public:
protected:
RegAllocBase(MachineFunction &Function, const TargetDescription &Target,
- const TargetRegisterAllocationInfo &TargetInfo, MachineAnalysisManager &Analyses,
- RegisterAllocationOptions Options, MachineActionReplay *Actions = nullptr) noexcept
+ const TargetRegisterAllocationInfo &TargetInfo,
+ MachineFunctionAnalysisManager &Analyses, RegisterAllocationOptions Options,
+ MachineActionReplay *Actions = nullptr) noexcept
: Function(Function), Target(Target), TargetInfo(TargetInfo), Analyses(Analyses),
Options(Options), Actions(Actions) {}
@@ -38,7 +39,7 @@ protected:
MachineFunction &Function;
const TargetDescription &Target;
const TargetRegisterAllocationInfo &TargetInfo;
- MachineAnalysisManager &Analyses;
+ MachineFunctionAnalysisManager &Analyses;
RegisterAllocationOptions Options;
MachineActionReplay *Actions = nullptr;
};
diff --git a/backend/lib/CodeGen/RegAllocBasic.cpp b/backend/lib/CodeGen/RegAllocBasic.cpp
index 9d14d15..7f730ca 100644
--- a/backend/lib/CodeGen/RegAllocBasic.cpp
+++ b/backend/lib/CodeGen/RegAllocBasic.cpp
@@ -18,7 +18,7 @@ class BasicAllocatorEngine final : public RegAllocBase {
public:
BasicAllocatorEngine(MachineFunction &Function, const TargetDescription &Target,
const TargetRegisterAllocationInfo &TargetInfo,
- MachineAnalysisManager &Analyses, RegisterAllocationOptions Options)
+ MachineFunctionAnalysisManager &Analyses, RegisterAllocationOptions Options)
: RegAllocBase(Function, Target, TargetInfo, Analyses, Options) {}
private:
@@ -80,7 +80,7 @@ private:
MachineFunctionProperty::TracksLiveness},
.Sets = {MachineFunctionProperty::NoVRegs},
.Clears = {},
- .RequiredAnalyses = {MachineAnalysisManager::id<LiveIntervalsAnalysis>()},
+ .RequiredAnalyses = {MachineFunctionAnalysisManager::id<LiveIntervalsAnalysis>()},
.VerificationStage = PipelineStage::RegisterAllocated,
};
Value.ThreadSafety = PassThreadSafety::ThreadSafe;
@@ -97,7 +97,7 @@ const MachinePassContract &BasicAllocatorPass::contract() const noexcept {
Expected<MachinePassResult> BasicAllocatorPass::run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &Analyses) {
+ MachineFunctionAnalysisManager &Analyses) {
if (Info == nullptr)
return makeUnexpected(ErrorCode::InvalidArgument, "BasicAllocator requires target behavior");
auto Required = regalloc_detail::requireAllocationProperties(Function, contract());
@@ -112,7 +112,7 @@ Expected<MachinePassResult> BasicAllocatorPass::run(MachineFunction &Function,
regalloc_detail::reserveFunctionRegisters(*Trial->ClonedFunction, FunctionReserved);
if (!TrialReserved)
return std::unexpected(TrialReserved.error());
- MachineAnalysisManager TrialAnalyses;
+ MachineFunctionAnalysisManager TrialAnalyses;
auto Registered = registerStage11MachineAnalyses(TrialAnalyses);
if (!Registered)
return std::unexpected(Registered.error());
diff --git a/backend/lib/CodeGen/RegAllocBasic.h b/backend/lib/CodeGen/RegAllocBasic.h
index 8a68f5f..f88c977 100644
--- a/backend/lib/CodeGen/RegAllocBasic.h
+++ b/backend/lib/CodeGen/RegAllocBasic.h
@@ -19,7 +19,7 @@ public:
[[nodiscard]] const MachinePassContract &contract() const noexcept override;
[[nodiscard]] Expected<MachinePassResult> run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &Analyses) override;
+ MachineFunctionAnalysisManager &Analyses) override;
private:
const TargetRegisterAllocationInfo *Info;
diff --git a/backend/lib/CodeGen/RegAllocFast.cpp b/backend/lib/CodeGen/RegAllocFast.cpp
index 1399f10..73c3e1a 100644
--- a/backend/lib/CodeGen/RegAllocFast.cpp
+++ b/backend/lib/CodeGen/RegAllocFast.cpp
@@ -557,7 +557,7 @@ const MachinePassContract &FastAllocatorPass::contract() const noexcept {
MachineFunctionProperty::TracksLiveness},
.Sets = {MachineFunctionProperty::NoVRegs},
.Clears = {},
- .RequiredAnalyses = {MachineAnalysisManager::id<LiveVariablesAnalysis>()},
+ .RequiredAnalyses = {MachineFunctionAnalysisManager::id<LiveVariablesAnalysis>()},
.VerificationStage = PipelineStage::RegisterAllocated,
};
Value.ThreadSafety = PassThreadSafety::ThreadSafe;
@@ -568,7 +568,7 @@ const MachinePassContract &FastAllocatorPass::contract() const noexcept {
Expected<MachinePassResult> FastAllocatorPass::run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &Analyses) {
+ MachineFunctionAnalysisManager &Analyses) {
if (Info == nullptr)
return makeUnexpected(ErrorCode::InvalidArgument, "FastAllocator requires target behavior");
auto Required = regalloc_detail::requireAllocationProperties(Function, contract());
@@ -583,7 +583,7 @@ Expected<MachinePassResult> FastAllocatorPass::run(MachineFunction &Function,
regalloc_detail::reserveFunctionRegisters(*Trial->ClonedFunction, FunctionReserved);
if (!TrialReserved)
return std::unexpected(TrialReserved.error());
- MachineAnalysisManager TrialAnalyses;
+ MachineFunctionAnalysisManager TrialAnalyses;
auto Registered = registerStage11MachineAnalyses(TrialAnalyses);
if (!Registered)
return std::unexpected(Registered.error());
diff --git a/backend/lib/CodeGen/RegAllocPBQP.cpp b/backend/lib/CodeGen/RegAllocPBQP.cpp
index 3b0e684..6706cd5 100644
--- a/backend/lib/CodeGen/RegAllocPBQP.cpp
+++ b/backend/lib/CodeGen/RegAllocPBQP.cpp
@@ -86,7 +86,7 @@ class PBQPAllocatorEngine final : public RegAllocBase {
public:
PBQPAllocatorEngine(MachineFunction &Function, const TargetDescription &Target,
const TargetRegisterAllocationInfo &TargetInfo,
- MachineAnalysisManager &Analyses, RegisterAllocationOptions Options,
+ MachineFunctionAnalysisManager &Analyses, RegisterAllocationOptions Options,
MachineActionReplay *Actions)
: RegAllocBase(Function, Target, TargetInfo, Analyses, Options, Actions) {}
@@ -277,7 +277,7 @@ private:
MachineFunctionProperty::TracksLiveness},
.Sets = {MachineFunctionProperty::NoVRegs},
.Clears = {},
- .RequiredAnalyses = {MachineAnalysisManager::id<LiveIntervalsAnalysis>()},
+ .RequiredAnalyses = {MachineFunctionAnalysisManager::id<LiveIntervalsAnalysis>()},
.VerificationStage = PipelineStage::RegisterAllocated,
};
Value.ThreadSafety = PassThreadSafety::ThreadSafe;
@@ -294,7 +294,7 @@ const MachinePassContract &PBQPAllocatorPass::contract() const noexcept {
Expected<MachinePassResult> PBQPAllocatorPass::run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &Analyses) {
+ MachineFunctionAnalysisManager &Analyses) {
if (Info == nullptr)
return makeUnexpected(ErrorCode::InvalidArgument, "PBQPAllocator requires target behavior");
auto Required = regalloc_detail::requireAllocationProperties(Function, contract());
@@ -309,7 +309,7 @@ Expected<MachinePassResult> PBQPAllocatorPass::run(MachineFunction &Function,
regalloc_detail::reserveFunctionRegisters(*Trial->ClonedFunction, FunctionReserved);
if (!TrialReserved)
return std::unexpected(TrialReserved.error());
- MachineAnalysisManager TrialAnalyses;
+ MachineFunctionAnalysisManager TrialAnalyses;
auto Registered = registerStage11MachineAnalyses(TrialAnalyses);
if (!Registered)
return std::unexpected(Registered.error());
diff --git a/backend/lib/CodeGen/SlotIndexes.cpp b/backend/lib/CodeGen/SlotIndexes.cpp
index 57e35b5..4fe753a 100644
--- a/backend/lib/CodeGen/SlotIndexes.cpp
+++ b/backend/lib/CodeGen/SlotIndexes.cpp
@@ -143,12 +143,12 @@ Expected<void> SlotIndexesAnalysis::Result::renumber(MachineFunction &Function)
bool SlotIndexesAnalysis::Result::invalidate(const MachineFunction &,
const PreservedAnalyses &Preserved) const noexcept {
- return !Preserved.preserves(MachineAnalysisManager::id<SlotIndexesAnalysis>());
+ return !Preserved.preserves(MachineFunctionAnalysisManager::id<SlotIndexesAnalysis>());
}
Expected<SlotIndexesAnalysis::Result> SlotIndexesAnalysis::run(MachineFunction &Function,
const TargetDescription &,
- MachineAnalysisManager &) {
+ MachineFunctionAnalysisManager &) {
Result ResultValue;
auto Numbered = ResultValue.renumber(Function);
if (!Numbered)
diff --git a/backend/lib/CodeGen/TwoAddressInstructionPass.cpp b/backend/lib/CodeGen/TwoAddressInstructionPass.cpp
index be4db82..b6f2a25 100644
--- a/backend/lib/CodeGen/TwoAddressInstructionPass.cpp
+++ b/backend/lib/CodeGen/TwoAddressInstructionPass.cpp
@@ -459,9 +459,9 @@ const MachinePassContract &TwoAddressInstructionPass::contract() const noexcept
return Contract;
}
-Expected<MachinePassResult> TwoAddressInstructionPass::run(MachineFunction &Function,
- const TargetDescription &Target,
- MachineAnalysisManager &Analyses) {
+Expected<MachinePassResult>
+TwoAddressInstructionPass::run(MachineFunction &Function, const TargetDescription &Target,
+ MachineFunctionAnalysisManager &Analyses) {
auto Required = requireProperties(Function, contract());
if (!Required)
return std::unexpected(Required.error());
diff --git a/backend/lib/CodeGen/VirtRegMap.cpp b/backend/lib/CodeGen/VirtRegMap.cpp
index a55a486..4f3ae45 100644
--- a/backend/lib/CodeGen/VirtRegMap.cpp
+++ b/backend/lib/CodeGen/VirtRegMap.cpp
@@ -169,7 +169,7 @@ Expected<bool> rewriteVirtualRegisters(MachineFunction &Function, const TargetDe
if (!MappingVerification)
return std::unexpected(MappingVerification.error());
- MachineAnalysisManager ValidationAnalyses;
+ MachineFunctionAnalysisManager ValidationAnalyses;
auto Registered = registerStage11MachineAnalyses(ValidationAnalyses);
if (!Registered)
return std::unexpected(Registered.error());
@@ -282,7 +282,7 @@ const MachinePassContract &VirtualRegisterRewritePass::contract() const noexcept
Expected<MachinePassResult> VirtualRegisterRewritePass::run(MachineFunction &Function,
const TargetDescription &Target,
- MachineAnalysisManager &) {
+ MachineFunctionAnalysisManager &) {
if (Mapping == nullptr)
return makeUnexpected(ErrorCode::InvalidArgument,
"VirtualRegisterRewrite requires a VirtRegMap");
diff --git a/backend/lib/Target/RISCV/RISCVPipeline.cpp b/backend/lib/Target/RISCV/RISCVPipeline.cpp
index c5601ef..60f798c 100644
--- a/backend/lib/Target/RISCV/RISCVPipeline.cpp
+++ b/backend/lib/Target/RISCV/RISCVPipeline.cpp
@@ -27,11 +27,12 @@ namespace rcc::riscv {
namespace {
template <typename PassT, typename... ArgumentT>
-[[nodiscard]] Expected<void> addPass(MachinePassManager &Pipeline, ArgumentT &&...Arguments) {
+[[nodiscard]] Expected<void> addPass(MachineFunctionPassManager &Pipeline,
+ ArgumentT &&...Arguments) {
return Pipeline.addPass(std::make_unique<PassT>(std::forward<ArgumentT>(Arguments)...));
}
-[[nodiscard]] Expected<void> addInitialPipeline(MachinePassManager &Pipeline,
+[[nodiscard]] Expected<void> addInitialPipeline(MachineFunctionPassManager &Pipeline,
const RISCVSubtarget &Subtarget) {
auto Added = addPass<MachineCombinerPass>(Pipeline, machineCombinerInfo(),
MachineCombinerStage::PreLegalizer);
@@ -46,7 +47,7 @@ template <typename PassT, typename... ArgumentT>
return addPass<InstructionSelect>(Pipeline, Subtarget.getInstructionSelector());
}
-[[nodiscard]] Expected<void> addSSAExitPipeline(MachinePassManager &Pipeline) {
+[[nodiscard]] Expected<void> addSSAExitPipeline(MachineFunctionPassManager &Pipeline) {
auto Added = addSelectedSSAOptimizationPipeline(Pipeline, optimizationPipelineInfo());
if (!Added)
return std::unexpected(Added.error());
@@ -56,14 +57,14 @@ template <typename PassT, typename... ArgumentT>
return addPass<TwoAddressInstructionPass>(Pipeline, instrInfo());
}
-[[nodiscard]] Expected<void> addRegisterAllocationPipeline(MachinePassManager &Pipeline) {
+[[nodiscard]] Expected<void> addRegisterAllocationPipeline(MachineFunctionPassManager &Pipeline) {
auto Added = addPreRegisterAllocationOptimizationPipeline(Pipeline, optimizationPipelineInfo());
if (!Added)
return std::unexpected(Added.error());
return addPass<PBQPAllocatorPass>(Pipeline, registerAllocationInfo());
}
-[[nodiscard]] Expected<void> addCompleteRegistry(MachinePassManager &Pipeline,
+[[nodiscard]] Expected<void> addCompleteRegistry(MachineFunctionPassManager &Pipeline,
const RISCVSubtarget &Subtarget) {
auto Added = addInitialPipeline(Pipeline, Subtarget);
if (!Added)
@@ -79,7 +80,8 @@ template <typename PassT, typename... ArgumentT>
} // namespace
-Expected<void> addCanonicalPipeline(MachinePassManager &Pipeline, const MachineFunction &Function,
+Expected<void> addCanonicalPipeline(MachineFunctionPassManager &Pipeline,
+ const MachineFunction &Function,
const RISCVSubtarget &Subtarget) {
if (!Function.properties().has(MachineFunctionProperty::Legalized)) {
auto Added = addPass<MachineCombinerPass>(Pipeline, machineCombinerInfo(),
@@ -132,11 +134,11 @@ Expected<std::unique_ptr<MachineFunctionPass>>
createCanonicalPipelinePass(std::string_view Name, const RISCVSubtarget &Subtarget) {
if (Name.empty())
return makeUnexpected(ErrorCode::InvalidArgument, "pipeline pass name cannot be empty");
- MachinePassManager Registry;
+ MachineFunctionPassManager Registry;
auto Added = addCompleteRegistry(Registry, Subtarget);
if (!Added)
return std::unexpected(Added.error());
- MachinePassManager::PassList Passes = std::move(Registry).takePasses();
+ MachineFunctionPassManager::PassList Passes = std::move(Registry).takePasses();
auto Position = std::ranges::find_if(Passes, [Name](const auto &Pass) {
return Pass != nullptr && Pass->contract().Name == Name;
});
@@ -149,11 +151,11 @@ createCanonicalPipelinePass(std::string_view Name, const RISCVSubtarget &Subtarg
Expected<std::vector<std::string>> canonicalPipelinePassNames(const MachineFunction &Function,
const RISCVSubtarget &Subtarget) {
- MachinePassManager Pipeline;
+ MachineFunctionPassManager Pipeline;
auto Added = addCanonicalPipeline(Pipeline, Function, Subtarget);
if (!Added)
return std::unexpected(Added.error());
- MachinePassManager::PassList Passes = std::move(Pipeline).takePasses();
+ MachineFunctionPassManager::PassList Passes = std::move(Pipeline).takePasses();
std::vector<std::string> Result;
Result.reserve(Passes.size());
for (const std::unique_ptr<MachineFunctionPass> &Pass : Passes) {
diff --git a/backend/lib/Tooling/PipelineDriver.cpp b/backend/lib/Tooling/PipelineDriver.cpp
index 495842a..d7a7d16 100644
--- a/backend/lib/Tooling/PipelineDriver.cpp
+++ b/backend/lib/Tooling/PipelineDriver.cpp
@@ -79,10 +79,10 @@ struct FunctionRunResult final {
return std::nullopt;
}
-[[nodiscard]] Expected<MachinePassManager::PassList>
+[[nodiscard]] Expected<MachineFunctionPassManager::PassList>
createPasses(const MachineFunction &Function, const BackendInvocation &Invocation,
const riscv::RISCVSubtarget &Subtarget, MachinePassManagerOptions Options) {
- MachinePassManager Pipeline(Options);
+ MachineFunctionPassManager Pipeline(Options);
if (Invocation.PassPipeline.size() == 1 && Invocation.PassPipeline.front() == "default") {
auto Added = riscv::addCanonicalPipeline(Pipeline, Function, Subtarget);
if (!Added)
@@ -212,7 +212,7 @@ runFunction(MachineFunction &Function, mir::MIRDocument &Document, const TargetD
auto Passes = createPasses(Function, Invocation, Subtarget, ManagerOptions);
if (!Passes)
return std::unexpected(Passes.error());
- MachineAnalysisManager Analyses;
+ MachineFunctionAnalysisManager Analyses;
auto Registered = registerMachineOptimizationAnalyses(Analyses);
if (!Registered)
return std::unexpected(Registered.error());
@@ -257,7 +257,7 @@ runFunction(MachineFunction &Function, mir::MIRDocument &Document, const TargetD
return std::unexpected(Captured.error());
}
- MachinePassManager SinglePass(ManagerOptions);
+ MachineFunctionPassManager SinglePass(ManagerOptions);
auto Added = SinglePass.addPass(std::move(Pass));
if (!Added)
return std::unexpected(Added.error());
diff --git a/backend/unittests/CodeGen/CMakeLists.txt b/backend/unittests/CodeGen/CMakeLists.txt
index 0715def..ac6ab36 100644
--- a/backend/unittests/CodeGen/CMakeLists.txt
+++ b/backend/unittests/CodeGen/CMakeLists.txt
@@ -27,7 +27,9 @@ set(
MachineMetadataTest.cpp
MachineOperandTest.cpp
MachineOptimizationTest.cpp
- MachinePassTest.cpp
+ PassManagerTest.cpp
+ PassInstrumentationTest.cpp
+ MachinePassManagerTest.cpp
MachineSchedulingTest.cpp
PBQPTest.cpp
RegisterAllocationTest.cpp
@@ -343,14 +345,35 @@ add_test(
COMMAND RCCBackendCodeGenMachineOperandTests
)
-add_executable(RCCBackendCodeGenMachinePassTests MachinePassTest.cpp)
-rcc_backend_configure_target(RCCBackendCodeGenMachinePassTests)
+add_executable(RCCBackendCodeGenPassManagerTests PassManagerTest.cpp)
+rcc_backend_configure_target(RCCBackendCodeGenPassManagerTests)
target_link_libraries(
- RCCBackendCodeGenMachinePassTests
+ RCCBackendCodeGenPassManagerTests
PRIVATE RCCBackend::CodeGen RCCBackend::TestTarget
)
+add_test(NAME RCCBackend.CodeGen.PassManager COMMAND RCCBackendCodeGenPassManagerTests)
-add_test(NAME RCCBackend.CodeGen.MachinePass COMMAND RCCBackendCodeGenMachinePassTests)
+add_executable(RCCBackendCodeGenPassInstrumentationTests PassInstrumentationTest.cpp)
+rcc_backend_configure_target(RCCBackendCodeGenPassInstrumentationTests)
+target_link_libraries(
+ RCCBackendCodeGenPassInstrumentationTests
+ PRIVATE RCCBackend::CodeGen RCCBackend::TestTarget
+)
+add_test(
+ NAME RCCBackend.CodeGen.PassInstrumentation
+ COMMAND RCCBackendCodeGenPassInstrumentationTests
+)
+
+add_executable(RCCBackendCodeGenMachinePassManagerTests MachinePassManagerTest.cpp)
+rcc_backend_configure_target(RCCBackendCodeGenMachinePassManagerTests)
+target_link_libraries(
+ RCCBackendCodeGenMachinePassManagerTests
+ PRIVATE RCCBackend::CodeGen RCCBackend::TestTarget
+)
+add_test(
+ NAME RCCBackend.CodeGen.MachinePassManager
+ COMMAND RCCBackendCodeGenMachinePassManagerTests
+)
add_subdirectory(GlobalISel)
@@ -495,7 +518,9 @@ rcc_backend_register_format_files(
"${CMAKE_CURRENT_SOURCE_DIR}/MachineMetadataTest.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/MachineOperandTest.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/MachineOptimizationTest.cpp"
- "${CMAKE_CURRENT_SOURCE_DIR}/MachinePassTest.cpp"
+ "${CMAKE_CURRENT_SOURCE_DIR}/PassManagerTest.cpp"
+ "${CMAKE_CURRENT_SOURCE_DIR}/PassInstrumentationTest.cpp"
+ "${CMAKE_CURRENT_SOURCE_DIR}/MachinePassManagerTest.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/MachineSchedulingTest.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/PBQPTest.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/RegisterAllocationTest.cpp"
@@ -544,7 +569,9 @@ rcc_backend_register_tidy_files(
"${CMAKE_CURRENT_SOURCE_DIR}/MachineMetadataTest.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/MachineOperandTest.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/MachineOptimizationTest.cpp"
- "${CMAKE_CURRENT_SOURCE_DIR}/MachinePassTest.cpp"
+ "${CMAKE_CURRENT_SOURCE_DIR}/PassManagerTest.cpp"
+ "${CMAKE_CURRENT_SOURCE_DIR}/PassInstrumentationTest.cpp"
+ "${CMAKE_CURRENT_SOURCE_DIR}/MachinePassManagerTest.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/MachineSchedulingTest.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/PBQPTest.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/RegisterAllocationTest.cpp"
diff --git a/backend/unittests/CodeGen/GlobalISel/InstructionSelectTest.cpp b/backend/unittests/CodeGen/GlobalISel/InstructionSelectTest.cpp
index e98f121..30c2b89 100644
--- a/backend/unittests/CodeGen/GlobalISel/InstructionSelectTest.cpp
+++ b/backend/unittests/CodeGen/GlobalISel/InstructionSelectTest.cpp
@@ -120,7 +120,7 @@ void testPipeline(TestContext &Context) {
Fixture.Function->properties() = {rcc::MachineFunctionProperty::IsSSA,
rcc::MachineFunctionProperty::TracksLiveness};
const rcc::riscv::RISCVSubtarget Subtarget(rcc::riscv::RISCVSubtargetFeatures::rv64gc());
- rcc::MachinePassManager Pipeline;
+ rcc::MachineFunctionPassManager Pipeline;
Context.expect(
Pipeline.addPass(std::make_unique<rcc::Legalizer>(Subtarget.getLegalizerInfo())).has_value(),
"legalizer must be accepted by the pass manager");
@@ -131,7 +131,7 @@ void testPipeline(TestContext &Context) {
Pipeline.addPass(std::make_unique<rcc::InstructionSelect>(Subtarget.getInstructionSelector()))
.has_value(),
"instruction selector must be accepted by the pass manager");
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
auto Run = Pipeline.run(*Fixture.Function, *Target, Analyses);
Context.expect(Run.has_value(), "RV64GC generic pipeline must complete");
Context.expect(Fixture.Function->properties().has(rcc::MachineFunctionProperty::Selected),
@@ -167,7 +167,7 @@ void testInstructionSelectionTransaction(TestContext &Context) {
rcc::MachineFunctionProperty::RegBankSelected};
MutatingFailingSelector Selector;
rcc::InstructionSelect Pass(Selector);
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
auto Run = Pass.run(*Fixture.Function, *Target, Analyses);
Context.expect(!Run && Run.error().code() == rcc::ErrorCode::Unsupported,
"a renderer failure must be reported before publication");
@@ -203,7 +203,7 @@ void testInstructionSelectionOrder(TestContext &Context) {
const rcc::riscv::RISCVSubtarget Subtarget(rcc::riscv::RISCVSubtargetFeatures::rv64gc());
RecordingSelector Selector(*Subtarget.getInstructionSelector());
rcc::InstructionSelect Pass(Selector);
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
auto Run = Pass.run(*Fixture.Function, *Target, Analyses);
Context.expect(Run.has_value(), "recorded instruction selection must complete");
std::ranges::reverse(LayoutIDs);
@@ -233,7 +233,7 @@ void testInstructionSelectionWorklist(TestContext &Context) {
rcc::MachineFunctionProperty::RegBankSelected};
TwoStepSelector Selector;
rcc::InstructionSelect Pass(Selector);
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
auto Run = Pass.run(*Fixture.Function, *Target, Analyses);
Context.expect(Run.has_value(), "a progressing multi-step selection must complete");
Context.expect(Selector.selections() == 4,
@@ -326,7 +326,7 @@ void testExtendedRV64GCPipeline(TestContext &Context) {
Fixture.Function->properties() = {rcc::MachineFunctionProperty::IsSSA,
rcc::MachineFunctionProperty::TracksLiveness};
const rcc::riscv::RISCVSubtarget Subtarget(rcc::riscv::RISCVSubtargetFeatures::rv64gc());
- rcc::MachinePassManager Pipeline;
+ rcc::MachineFunctionPassManager Pipeline;
if (!Pipeline.addPass(std::make_unique<rcc::Legalizer>(Subtarget.getLegalizerInfo())) ||
!Pipeline.addPass(std::make_unique<rcc::RegBankSelect>(Subtarget.getRegBankInfo())) ||
!Pipeline.addPass(
@@ -334,7 +334,7 @@ void testExtendedRV64GCPipeline(TestContext &Context) {
Context.expect(false, "extended RV64GC pipeline construction must succeed");
return;
}
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
auto Run = Pipeline.run(*Fixture.Function, *Target, Analyses);
Context.expect(Run.has_value(), "extended RV64GC pipeline must complete");
Context.expect(Run && Fixture.Function->properties().has(rcc::MachineFunctionProperty::Selected),
diff --git a/backend/unittests/CodeGen/GlobalISel/LegalizerTest.cpp b/backend/unittests/CodeGen/GlobalISel/LegalizerTest.cpp
index 9cb8a67..b191a3f 100644
--- a/backend/unittests/CodeGen/GlobalISel/LegalizerTest.cpp
+++ b/backend/unittests/CodeGen/GlobalISel/LegalizerTest.cpp
@@ -73,7 +73,7 @@ void testNullAndMissingContracts(TestContext &Context) {
return;
rcc::Legalizer NullPass(nullptr);
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
auto NullResult = NullPass.run(*Fixture.Function, *Target, Analyses);
Context.expect(!NullResult && NullResult.error().code() == rcc::ErrorCode::InvalidArgument,
"a null legalizer interface must be rejected");
@@ -117,12 +117,12 @@ void testUnsupportedRollback(TestContext &Context) {
Unsupported.Function->properties() = {rcc::MachineFunctionProperty::IsSSA,
rcc::MachineFunctionProperty::TracksLiveness};
const rcc::riscv::RISCVSubtarget Subtarget(rcc::riscv::RISCVSubtargetFeatures::rv64gc());
- rcc::MachinePassManager OnlyLegalizer;
+ rcc::MachineFunctionPassManager OnlyLegalizer;
Context.expect(
OnlyLegalizer.addPass(std::make_unique<rcc::Legalizer>(Subtarget.getLegalizerInfo()))
.has_value(),
"standalone legalizer must be accepted");
- rcc::MachineAnalysisManager UnsupportedAnalyses;
+ rcc::MachineFunctionAnalysisManager UnsupportedAnalyses;
auto Failure = OnlyLegalizer.run(*Unsupported.Function, *Target, UnsupportedAnalyses);
Context.expect(!Failure && Failure.error().code() == rcc::ErrorCode::Unsupported,
"unsupported generic instructions must produce a target diagnostic");
@@ -152,7 +152,7 @@ void testLegalizerCycleDiagnostic(TestContext &Context) {
rcc::MachineFunctionProperty::TracksLiveness};
TogglingLegalizer Legalizer;
rcc::Legalizer StablePass(Legalizer);
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
auto ResultRun = StablePass.run(*Fixture.Function, *Target, Analyses);
Context.expect(!ResultRun && ResultRun.error().code() == rcc::ErrorCode::InternalError,
"repeated legalization states must report InternalError");
@@ -188,7 +188,7 @@ void testLegalizerRevisitsInvalidatedInstructions(TestContext &Context) {
rcc::MachineFunctionProperty::TracksLiveness};
BackwardInvalidatingLegalizer Legalizer;
rcc::Legalizer Pass(Legalizer);
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
auto Run = Pass.run(*Fixture.Function, *Target, Analyses);
const rcc::Opcode LegalOpcode =
rcc::Opcode::fromValue(static_cast<std::uint32_t>(rcc::riscv::InstructionOpcode::ADD));
diff --git a/backend/unittests/CodeGen/GlobalISel/RegBankSelectTest.cpp b/backend/unittests/CodeGen/GlobalISel/RegBankSelectTest.cpp
index d4925eb..833435f 100644
--- a/backend/unittests/CodeGen/GlobalISel/RegBankSelectTest.cpp
+++ b/backend/unittests/CodeGen/GlobalISel/RegBankSelectTest.cpp
@@ -33,7 +33,7 @@ void testBankConflict(TestContext &Context) {
Fixture.Function->properties() = {rcc::MachineFunctionProperty::Legalized};
const rcc::riscv::RISCVSubtarget Subtarget(rcc::riscv::RISCVSubtargetFeatures::rv64gc());
rcc::RegBankSelect Pass(Subtarget.getRegBankInfo());
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
auto Result = Pass.run(*Fixture.Function, *Target, Analyses);
Context.expect(!Result && Result.error().code() == rcc::ErrorCode::VerificationError,
"bank selection must reject a conflicting pre-existing bank");
@@ -66,7 +66,7 @@ void testBankClassOnlyChange(TestContext &Context) {
Fixture.Function->properties() = {rcc::MachineFunctionProperty::Legalized};
const rcc::riscv::RISCVSubtarget Subtarget(rcc::riscv::RISCVSubtargetFeatures::rv64gc());
rcc::RegBankSelect Pass(Subtarget.getRegBankInfo());
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
auto Result = Pass.run(*Fixture.Function, *Target, Analyses);
Context.expect(Result.has_value() && Result->Changed &&
Result->Changes.has(rcc::MachinePassChange::Registers),
diff --git a/backend/unittests/CodeGen/LiveIntervalTest.cpp b/backend/unittests/CodeGen/LiveIntervalTest.cpp
index 7e48b05..34ebd76 100644
--- a/backend/unittests/CodeGen/LiveIntervalTest.cpp
+++ b/backend/unittests/CodeGen/LiveIntervalTest.cpp
@@ -74,7 +74,7 @@ void testLaneSubrangesAndEarlyClobber(TestContext &Context, const rcc::TargetDes
return;
}
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
auto Registered = rcc::registerStage11MachineAnalyses(Analyses);
auto Intervals = Registered
? Analyses.getResult<rcc::LiveIntervalsAnalysis>(*Fixture->Function, Target)
diff --git a/backend/unittests/CodeGen/LiveIntervalsTest.cpp b/backend/unittests/CodeGen/LiveIntervalsTest.cpp
index 5c127a2..a080e4d 100644
--- a/backend/unittests/CodeGen/LiveIntervalsTest.cpp
+++ b/backend/unittests/CodeGen/LiveIntervalsTest.cpp
@@ -64,7 +64,7 @@ void testCFGAndValueNumbers(TestContext &Context, const rcc::TargetDescription &
return;
}
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
auto Registered = rcc::registerStage11MachineAnalyses(Analyses);
auto Variables = Registered ? Analyses.getResult<rcc::LiveVariablesAnalysis>(Function, Target)
: rcc::Expected<rcc::LiveVariablesAnalysis::Result *>{
@@ -133,7 +133,7 @@ void testPhysicalUnitsAndRegMasks(TestContext &Context, const rcc::TargetDescrip
Context.expect(false, "physical-alias instructions must be built");
return;
}
- rcc::MachineAnalysisManager AliasAnalyses;
+ rcc::MachineFunctionAnalysisManager AliasAnalyses;
auto AliasRegistered = rcc::registerStage11MachineAnalyses(AliasAnalyses);
auto AliasIntervals =
AliasRegistered
@@ -167,7 +167,7 @@ void testPhysicalUnitsAndRegMasks(TestContext &Context, const rcc::TargetDescrip
Context.expect(false, "RegMask instructions must be built");
return;
}
- rcc::MachineAnalysisManager MaskAnalyses;
+ rcc::MachineFunctionAnalysisManager MaskAnalyses;
auto MaskRegistered = rcc::registerStage11MachineAnalyses(MaskAnalyses);
auto MaskIntervals =
MaskRegistered
@@ -237,7 +237,7 @@ void testRISCVLiveness(TestContext &Context) {
Context.expect(false, "RV64GC ADDI instructions must be built");
return;
}
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
auto Registered = rcc::registerStage11MachineAnalyses(Analyses);
auto Intervals = Registered
? Analyses.getResult<rcc::LiveIntervalsAnalysis>(*Fixture->Function, *Target)
diff --git a/backend/unittests/CodeGen/LivePhysRegsTest.cpp b/backend/unittests/CodeGen/LivePhysRegsTest.cpp
index ee579be..6eea796 100644
--- a/backend/unittests/CodeGen/LivePhysRegsTest.cpp
+++ b/backend/unittests/CodeGen/LivePhysRegsTest.cpp
@@ -24,7 +24,7 @@ void testPostRALivenessRepair(TestContext &Context, const rcc::TargetDescription
return;
}
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
auto Registered = rcc::registerStage11MachineAnalyses(Analyses);
auto Liveness = Registered
? Analyses.getResult<rcc::LiveVariablesAnalysis>(*Fixture->Function, Target)
diff --git a/backend/unittests/CodeGen/LiveRegMatrixTest.cpp b/backend/unittests/CodeGen/LiveRegMatrixTest.cpp
index 21c0778..423da50 100644
--- a/backend/unittests/CodeGen/LiveRegMatrixTest.cpp
+++ b/backend/unittests/CodeGen/LiveRegMatrixTest.cpp
@@ -26,7 +26,7 @@ void testLaneAndAssignment(TestContext &Context, const TargetDescription &Target
!buildUse(*Fixture->Function, Target, *Fixture->Block, *Low, TestSubReg::Low32))
return;
- MachineAnalysisManager Analyses;
+ MachineFunctionAnalysisManager Analyses;
if (!registerStage11MachineAnalyses(Analyses))
return;
auto Intervals = Analyses.getResult<LiveIntervalsAnalysis>(*Fixture->Function, Target);
@@ -55,7 +55,7 @@ void testFixedAndMaskInterference(TestContext &Context, const TargetDescription
!buildUse(*Fixture->Function, Target, *Fixture->Block, *Value))
return;
- MachineAnalysisManager Analyses;
+ MachineFunctionAnalysisManager Analyses;
if (!registerStage11MachineAnalyses(Analyses))
return;
auto Intervals = Analyses.getResult<LiveIntervalsAnalysis>(*Fixture->Function, Target);
diff --git a/backend/unittests/CodeGen/LiveVariablesTest.cpp b/backend/unittests/CodeGen/LiveVariablesTest.cpp
index 577ecde..1cc4e91 100644
--- a/backend/unittests/CodeGen/LiveVariablesTest.cpp
+++ b/backend/unittests/CodeGen/LiveVariablesTest.cpp
@@ -36,9 +36,9 @@ void testLivenessRebuildAndVerifier(TestContext &Context, const rcc::TargetDescr
Context.expect(StaleLiveIn.has_value(), "stale live-in setup must succeed");
setRebuildProperties(Function);
- rcc::MachinePassManager Pipeline;
+ rcc::MachineFunctionPassManager Pipeline;
auto Added = Pipeline.addPass(std::make_unique<rcc::RebuildMachineLivenessPass>());
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
auto Run = Added ? Pipeline.run(Function, Target, Analyses)
: rcc::Expected<void>{std::unexpected(Added.error())};
if (!Run)
@@ -169,8 +169,9 @@ class DummyAnalysis final {
public:
struct Result final {};
- [[nodiscard]] static rcc::Expected<Result>
- run(rcc::MachineFunction &, const rcc::TargetDescription &, rcc::MachineAnalysisManager &) {
+ [[nodiscard]] static rcc::Expected<Result> run(rcc::MachineFunction &,
+ const rcc::TargetDescription &,
+ rcc::MachineFunctionAnalysisManager &) {
return Result{};
}
};
@@ -192,7 +193,7 @@ void testAnalysisRegistrationAndInvalidation(TestContext &Context,
return;
}
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
auto FirstRegistration = rcc::registerStage11MachineAnalyses(Analyses);
auto SecondRegistration = rcc::registerStage11MachineAnalyses(Analyses);
auto Intervals = FirstRegistration
@@ -211,7 +212,7 @@ void testAnalysisRegistrationAndInvalidation(TestContext &Context,
Context.expect(
Analyses.cachedResultCount(*Fixture->Function) == 1 &&
Analyses.hasCached(*Fixture->Function,
- rcc::MachineAnalysisManager::id<rcc::SlotIndexesAnalysis>()),
+ rcc::MachineFunctionAnalysisManager::id<rcc::SlotIndexesAnalysis>()),
"operand changes must retain SlotIndexes while invalidating liveness dependents");
auto Recomputed = Analyses.getResult<rcc::LiveIntervalsAnalysis>(*Fixture->Function, Target);
Context.expect(Recomputed && Analyses.cachedResultCount(*Fixture->Function) == 3,
@@ -221,18 +222,21 @@ void testAnalysisRegistrationAndInvalidation(TestContext &Context,
Context.expect(
Analyses.cachedResultCount(*Fixture->Function) == 1 &&
Analyses.hasCached(*Fixture->Function,
- rcc::MachineAnalysisManager::id<rcc::LiveVariablesAnalysis>()),
+ rcc::MachineFunctionAnalysisManager::id<rcc::LiveVariablesAnalysis>()),
"layout changes must invalidate SlotIndexes and LiveIntervals only");
- rcc::MachineAnalysisManager Atomic;
+ rcc::MachineFunctionAnalysisManager Atomic;
rcc::MachineAnalysisRegistration DummyRegistration;
DummyRegistration.Name = "SlotIndexes";
auto Dummy = Atomic.registerAnalysis<DummyAnalysis>(std::move(DummyRegistration));
auto Rejected = rcc::registerStage11MachineAnalyses(Atomic);
Context.expect(
- Dummy && !Rejected && Atomic.isRegistered(rcc::MachineAnalysisManager::id<DummyAnalysis>()) &&
- !Atomic.isRegistered(rcc::MachineAnalysisManager::id<rcc::SlotIndexesAnalysis>()) &&
- !Atomic.isRegistered(rcc::MachineAnalysisManager::id<rcc::LiveVariablesAnalysis>()),
+ Dummy && !Rejected &&
+ Atomic.isRegistered(rcc::MachineFunctionAnalysisManager::id<DummyAnalysis>()) &&
+ !Atomic.isRegistered(
+ rcc::MachineFunctionAnalysisManager::id<rcc::SlotIndexesAnalysis>()) &&
+ !Atomic.isRegistered(
+ rcc::MachineFunctionAnalysisManager::id<rcc::LiveVariablesAnalysis>()),
"failed standard-analysis registration must leave the manager unchanged");
}
diff --git a/backend/unittests/CodeGen/MachineAnalysesTest.cpp b/backend/unittests/CodeGen/MachineAnalysesTest.cpp
index 1c9f255..997d031 100644
--- a/backend/unittests/CodeGen/MachineAnalysesTest.cpp
+++ b/backend/unittests/CodeGen/MachineAnalysesTest.cpp
@@ -86,7 +86,7 @@ void testCFGAnalyses(TestContext &Context, const rcc::TargetDescription &Target)
Updater.addSuccessor(**Body, **Header, rcc::BranchProbability::one()),
"reducible loop CFG construction must succeed");
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
Context.expect(rcc::registerStage8MachineAnalyses(Analyses).has_value(),
"standard Stage 8 analyses must register atomically");
auto Dominators = Analyses.getResult<rcc::MachineDominatorTreeAnalysis>(**Function, Target);
@@ -129,7 +129,7 @@ void testCFGAnalyses(TestContext &Context, const rcc::TargetDescription &Target)
Context.expect(
Analyses.cachedResultCount(**Function) == 1 &&
Analyses.hasCached(**Function,
- rcc::MachineAnalysisManager::id<rcc::MachineAliasAnalysis>()),
+ rcc::MachineFunctionAnalysisManager::id<rcc::MachineAliasAnalysis>()),
"CFG changes must invalidate CFG dependents and memory dependence but preserve aliasing");
auto RefreshedDominators =
@@ -167,7 +167,7 @@ void testIrreducibleCFG(TestContext &Context, const rcc::TargetDescription &Targ
Updater.addSuccessor(**Right, **Exit, *Half),
"irreducible CFG construction must succeed");
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
auto Registered = rcc::registerStage8MachineAnalyses(Analyses);
auto Loops =
Registered
@@ -317,7 +317,7 @@ void testMemoryDependence(TestContext &Context, const rcc::TargetDescription &Ta
!VolatileStoreInstruction || !VolatileLoadInstruction || !OtherBlockLoadInstruction)
return;
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
auto Registered = rcc::registerStage8MachineAnalyses(Analyses);
auto Dependencies =
Registered ? Analyses.getResult<rcc::MachineMemoryDependenceAnalysis>(**Function, Target)
@@ -352,14 +352,15 @@ void testMemoryDependence(TestContext &Context, const rcc::TargetDescription &Ta
class ConflictingAnalysis final {
public:
struct Result final {};
- [[nodiscard]] static rcc::Expected<Result>
- run(rcc::MachineFunction &, const rcc::TargetDescription &, rcc::MachineAnalysisManager &) {
+ [[nodiscard]] static rcc::Expected<Result> run(rcc::MachineFunction &,
+ const rcc::TargetDescription &,
+ rcc::MachineFunctionAnalysisManager &) {
return Result{};
}
};
void testAtomicStandardRegistration(TestContext &Context) {
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
Context.expect(Analyses
.registerAnalysis<ConflictingAnalysis>({
.Name = "MachineLoopInfo",
@@ -367,10 +368,11 @@ void testAtomicStandardRegistration(TestContext &Context) {
})
.has_value(),
"analysis-name conflict setup must succeed");
- Context.expect(!rcc::registerStage8MachineAnalyses(Analyses) &&
- !Analyses.isRegistered(
- rcc::MachineAnalysisManager::id<rcc::MachineDominatorTreeAnalysis>()),
- "failed standard-analysis registration must not publish a partial set");
+ Context.expect(
+ !rcc::registerStage8MachineAnalyses(Analyses) &&
+ !Analyses.isRegistered(
+ rcc::MachineFunctionAnalysisManager::id<rcc::MachineDominatorTreeAnalysis>()),
+ "failed standard-analysis registration must not publish a partial set");
}
void testCFGUpdaterPHIs(TestContext &Context, const rcc::TargetDescription &Target) {
diff --git a/backend/unittests/CodeGen/MachineOptimizationTest.cpp b/backend/unittests/CodeGen/MachineOptimizationTest.cpp
index d246e39..bb2c0e1 100644
--- a/backend/unittests/CodeGen/MachineOptimizationTest.cpp
+++ b/backend/unittests/CodeGen/MachineOptimizationTest.cpp
@@ -321,7 +321,7 @@ void testDCEFixedPointAndDebugUses(TestContext &Context, const rcc::TargetDescri
}
const std::size_t Before = Fixture.Entry->instructionCount();
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
rcc::MachineDCEPass Pass;
auto Result = Pass.run(*Fixture.Function, Target, Analyses);
if (!Result)
@@ -369,7 +369,7 @@ void testMachineCombinerIdentityRules(TestContext &Context, const rcc::TargetDes
return;
(void)buildStore(Context, Builder, Consumer, X2, *Memory);
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
rcc::MachineCombinerPass Pass(rcc::riscv::machineCombinerInfo(),
rcc::MachineCombinerStage::SelectedSSA);
auto Result = Pass.run(*Fixture.Function, Target, Analyses);
@@ -404,7 +404,7 @@ void testPostRAMachineCombinerIdentity(TestContext &Context, const rcc::TargetDe
rcc::Register::fromPhysical(X10), 0);
if (FrameIdentity != nullptr)
FrameIdentity->setFlags({rcc::MachineInstrFlag::FrameDestroy});
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
rcc::MachineCombinerPass Pass(rcc::riscv::machineCombinerInfo(),
rcc::MachineCombinerStage::PostRegisterAllocation);
auto Result = Pass.run(*Fixture.Function, Target, Analyses);
@@ -450,7 +450,7 @@ void testCSERegisterAndMemoryRules(TestContext &Context, const rcc::TargetDescri
rcc::MachineInstr *InvariantTwo =
buildLoad(Context, Builder, InvariantLoadTwo, Seed, *InvariantMemory);
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
rcc::MachineCSEPass Pass;
auto Result = Pass.run(*Fixture.Function, Target, Analyses);
if (!Result)
@@ -490,7 +490,7 @@ void testCSEBudgetPreservesLegalMIR(TestContext &Context, const rcc::TargetDescr
(void)buildADDI(Context, Builder, First, Seed, 2);
rcc::MachineInstr *SecondInstruction = buildADDI(Context, Builder, Second, Seed, 2);
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
rcc::MachineCSEPass Pass({.MaximumComparisons = 0});
auto Result = Pass.run(*Fixture.Function, Target, Analyses);
if (!Result)
@@ -545,7 +545,7 @@ void testLICMHoistsOnlyInvariantInstructions(TestContext &Context,
rcc::MachineInstr *Load =
Memory == nullptr ? nullptr : buildLoad(Context, Builder, MutableLoad, Seed, *Memory);
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
rcc::MachineLICMPass Pass;
auto Result = Pass.run(*Fixture.Function, Target, Analyses);
if (!Result)
@@ -597,7 +597,7 @@ void testMachineSinkUsesColdUniqueSuccessor(TestContext &Context,
const rcc::Register Consumer = makeGPR(Context, *Fixture.Function);
rcc::MachineInstr *Use = buildADD(Context, Builder, Consumer, SunkValue, Seed);
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
rcc::MachineSinkPass Pass;
auto Result = Pass.run(*Fixture.Function, Target, Analyses);
if (!Result)
@@ -664,7 +664,7 @@ void testPostRACodeMotion(TestContext &Context, const rcc::TargetDescription &Ta
setPostRAProperties(*LICMFixture.Function);
Context.expect(rcc::rebuildMachineLiveness(*LICMFixture.Function, Target).has_value(),
"post-RA LICM fixture liveness must be built");
- rcc::MachineAnalysisManager LICMAnalyses;
+ rcc::MachineFunctionAnalysisManager LICMAnalyses;
rcc::MachineLICMPass PostRALICM(rcc::MachineCodeMotionStage::PostRegisterAllocation);
auto LICMResult = PostRALICM.run(*LICMFixture.Function, Target, LICMAnalyses);
Context.expect(LICMResult && LICMResult->Changed && Hoisted->parent() == LICMFixture.Entry &&
@@ -703,7 +703,7 @@ void testPostRACodeMotion(TestContext &Context, const rcc::TargetDescription &Ta
setPostRAProperties(*SinkFixture.Function);
Context.expect(rcc::rebuildMachineLiveness(*SinkFixture.Function, Target).has_value(),
"post-RA sink fixture liveness must be built");
- rcc::MachineAnalysisManager SinkAnalyses;
+ rcc::MachineFunctionAnalysisManager SinkAnalyses;
rcc::MachineSinkPass PostRASink(rcc::MachineCodeMotionStage::PostRegisterAllocation);
auto SinkResult = PostRASink.run(*SinkFixture.Function, Target, SinkAnalyses);
Context.expect(SinkResult && SinkResult->Changed && Sunk->parent() == *Cold &&
@@ -742,7 +742,7 @@ void testMemoryFoldingContract(TestContext &Context, const rcc::TargetDescriptio
if (!Folded.Function || Folded.Entry == nullptr)
return;
TestMemoryFoldingInfo GoodInfo;
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
rcc::MachineMemoryFoldingPass Pass(GoodInfo);
auto Result = Pass.run(*Folded.Function, Target, Analyses);
if (!Result)
diff --git a/backend/unittests/CodeGen/MachinePassManagerTest.cpp b/backend/unittests/CodeGen/MachinePassManagerTest.cpp
new file mode 100644
index 0000000..6e6c44d
--- /dev/null
+++ b/backend/unittests/CodeGen/MachinePassManagerTest.cpp
@@ -0,0 +1,426 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "rcc/CodeGen/MachinePassManager.h"
+
+#include "Target/TestTarget.h"
+#include "rcc/CodeGen/CompilationUnit.h"
+#include "rcc/CodeGen/GenericOpcodes.h"
+#include "rcc/CodeGen/MachineFunction.h"
+
+#include <atomic>
+#include <cstddef>
+#include <cstdint>
+#include <iostream>
+#include <memory>
+#include <string>
+#include <string_view>
+#include <utility>
+#include <vector>
+
+namespace {
+
+class TestContext final {
+public:
+ void expect(bool Condition, std::string_view Message) {
+ if (Condition)
+ return;
+ std::cerr << Message << '\n';
+ ++Failures;
+ }
+
+ [[nodiscard]] int result() const noexcept {
+ return Failures == 0 ? 0 : 1;
+ }
+
+private:
+ int Failures = 0;
+};
+
+[[nodiscard]] rcc::Expected<rcc::TargetDescription> createTarget() {
+ std::vector<rcc::InstructionDescriptor> Descriptors;
+ std::vector<rcc::ImmediatePredicate> Predicates;
+ auto Appended = rcc::appendGenericInstructionInfo(Descriptors, Predicates);
+ if (!Appended)
+ return std::unexpected(Appended.error());
+ auto Instructions = rcc::InstructionSet::create(std::move(Descriptors), std::move(Predicates));
+ if (!Instructions)
+ return std::unexpected(Instructions.error());
+ return rcc::test::createTestTargetDescription(std::move(*Instructions));
+}
+
+class BlockCountAnalysis final {
+public:
+ struct Result final {
+ std::size_t Count = 0;
+ };
+
+ [[nodiscard]] static constexpr std::string_view name() noexcept {
+ return "BlockCount";
+ }
+
+ [[nodiscard]] static rcc::Expected<Result> run(rcc::MachineFunction &Function,
+ const rcc::TargetDescription &,
+ rcc::MachineFunctionAnalysisManager &) {
+ return Result{Function.blockCount()};
+ }
+};
+
+class NonThreadSafeAnalysis final {
+public:
+ struct Result final {};
+
+ [[nodiscard]] static constexpr std::string_view name() noexcept {
+ return "NonThreadSafe";
+ }
+
+ [[nodiscard]] static rcc::Expected<Result> run(rcc::MachineFunction &,
+ const rcc::TargetDescription &,
+ rcc::MachineFunctionAnalysisManager &) {
+ return Result{};
+ }
+};
+
+class RequiredAnalysisPass final : public rcc::MachineFunctionPass {
+public:
+ [[nodiscard]] const rcc::MachinePassContract &contract() const noexcept override {
+ static const rcc::MachinePassContract Contract{
+ .Name = "RequiredAnalysis",
+ .Requires = {},
+ .Sets = {},
+ .Clears = {},
+ .RequiredAnalyses = {rcc::MachineFunctionAnalysisManager::id<BlockCountAnalysis>()},
+ .VerificationStage = std::nullopt,
+ };
+ return Contract;
+ }
+
+ [[nodiscard]] rcc::Expected<rcc::MachinePassResult>
+ run(rcc::MachineFunction &Function, const rcc::TargetDescription &Target,
+ rcc::MachineFunctionAnalysisManager &Analyses) override {
+ auto Blocks = Analyses.getResult<BlockCountAnalysis>(Function, Target);
+ if (!Blocks)
+ return std::unexpected(Blocks.error());
+ rcc::MachinePassResult Result;
+ Result.Preserved = rcc::PreservedAnalyses::all();
+ return Result;
+ }
+};
+
+class UnreportedChangePass final : public rcc::MachineFunctionPass {
+public:
+ [[nodiscard]] const rcc::MachinePassContract &contract() const noexcept override {
+ static const rcc::MachinePassContract Contract{
+ .Name = "UnreportedChange",
+ .Requires = {},
+ .Sets = {},
+ .Clears = {},
+ .RequiredAnalyses = {},
+ .VerificationStage = std::nullopt,
+ };
+ return Contract;
+ }
+
+ [[nodiscard]] rcc::Expected<rcc::MachinePassResult>
+ run(rcc::MachineFunction &Function, const rcc::TargetDescription &,
+ rcc::MachineFunctionAnalysisManager &) override {
+ auto Block = Function.createBasicBlock();
+ if (!Block)
+ return std::unexpected(Block.error());
+ auto Appended = Function.appendBlock(**Block);
+ if (!Appended)
+ return std::unexpected(Appended.error());
+ return rcc::MachinePassResult{};
+ }
+};
+
+class MutatingFailurePass final : public rcc::MachineFunctionPass {
+public:
+ [[nodiscard]] const rcc::MachinePassContract &contract() const noexcept override {
+ static const rcc::MachinePassContract Contract{
+ .Name = "MutatingFailure",
+ .Requires = {},
+ .Sets = {},
+ .Clears = {},
+ .RequiredAnalyses = {rcc::MachineFunctionAnalysisManager::id<BlockCountAnalysis>()},
+ .VerificationStage = std::nullopt,
+ };
+ return Contract;
+ }
+
+ [[nodiscard]] rcc::Expected<rcc::MachinePassResult>
+ run(rcc::MachineFunction &Function, const rcc::TargetDescription &,
+ rcc::MachineFunctionAnalysisManager &) override {
+ auto Block = Function.createBasicBlock();
+ if (!Block)
+ return std::unexpected(Block.error());
+ auto Appended = Function.appendBlock(**Block);
+ if (!Appended)
+ return std::unexpected(Appended.error());
+ return rcc::makeUnexpected(rcc::ErrorCode::VerificationError,
+ "intentional mutating pass failure");
+ }
+};
+
+class ParallelCountingPass final : public rcc::MachineFunctionPass {
+public:
+ explicit ParallelCountingPass(std::atomic<std::uint32_t> &Count) : Count(&Count) {}
+
+ [[nodiscard]] const rcc::MachinePassContract &contract() const noexcept override {
+ static const rcc::MachinePassContract Contract = [] {
+ rcc::MachinePassContract Value{
+ .Name = "ParallelCounting",
+ .Requires = {},
+ .Sets = {},
+ .Clears = {},
+ .RequiredAnalyses = {},
+ .VerificationStage = std::nullopt,
+ };
+ Value.ThreadSafety = rcc::PassThreadSafety::ThreadSafe;
+ return Value;
+ }();
+ return Contract;
+ }
+
+ [[nodiscard]] rcc::Expected<rcc::MachinePassResult>
+ run(rcc::MachineFunction &, const rcc::TargetDescription &,
+ rcc::MachineFunctionAnalysisManager &) override {
+ Count->fetch_add(1, std::memory_order_relaxed);
+ return rcc::MachinePassResult{};
+ }
+
+private:
+ std::atomic<std::uint32_t> *Count;
+};
+
+class RequiresNonThreadSafeAnalysisPass final : public rcc::MachineFunctionPass {
+public:
+ [[nodiscard]] const rcc::MachinePassContract &contract() const noexcept override {
+ static const rcc::MachinePassContract Contract = [] {
+ rcc::MachinePassContract Value{
+ .Name = "RequiresNonThreadSafe",
+ .Requires = {},
+ .Sets = {},
+ .Clears = {},
+ .RequiredAnalyses =
+ {
+ rcc::MachineFunctionAnalysisManager::id<NonThreadSafeAnalysis>(),
+ },
+ .VerificationStage = std::nullopt,
+ };
+ Value.ThreadSafety = rcc::PassThreadSafety::ThreadSafe;
+ return Value;
+ }();
+ return Contract;
+ }
+
+ [[nodiscard]] rcc::Expected<rcc::MachinePassResult>
+ run(rcc::MachineFunction &, const rcc::TargetDescription &,
+ rcc::MachineFunctionAnalysisManager &) override {
+ return rcc::MachinePassResult{};
+ }
+};
+
+class UnitFunctionCountAnalysis final {
+public:
+ struct Result final {
+ std::size_t Count = 0;
+ };
+ [[nodiscard]] static constexpr std::string_view name() noexcept {
+ return "UnitFunctionCount";
+ }
+ [[nodiscard]] static rcc::Expected<Result> run(rcc::CompilationUnit &Unit,
+ const rcc::TargetDescription &,
+ rcc::CompilationUnitAnalysisManager &) {
+ return Result{Unit.functionCount()};
+ }
+};
+
+class ObserveUnitPass final : public rcc::CompilationUnitPass {
+public:
+ [[nodiscard]] const rcc::CompilationUnitPassContract &contract() const noexcept override {
+ static const rcc::CompilationUnitPassContract Contract{
+ .Name = "ObserveUnit",
+ .RequiredAnalyses = {rcc::CompilationUnitAnalysisManager::id<UnitFunctionCountAnalysis>()},
+ .Parameters = {},
+ .DeclaredChanges = {},
+ };
+ return Contract;
+ }
+
+ [[nodiscard]] rcc::Expected<rcc::CompilationUnitPassResult>
+ run(rcc::CompilationUnit &Unit, const rcc::TargetDescription &Target,
+ rcc::CompilationUnitAnalysisManager &Analyses,
+ rcc::MachineFunctionAnalysisManager &) override {
+ auto Count = Analyses.getResult<UnitFunctionCountAnalysis>(Unit, Target);
+ if (!Count)
+ return std::unexpected(Count.error());
+ if ((*Count)->Count != Unit.functionCount()) {
+ return rcc::makeUnexpected(rcc::ErrorCode::VerificationError,
+ "unit analysis returned a stale function count");
+ }
+ return rcc::CompilationUnitPassResult{};
+ }
+};
+
+class MutatingUnitFailurePass final : public rcc::CompilationUnitPass {
+public:
+ [[nodiscard]] const rcc::CompilationUnitPassContract &contract() const noexcept override {
+ static const rcc::CompilationUnitPassContract Contract{
+ .Name = "MutatingUnitFailure",
+ .RequiredAnalyses = {rcc::CompilationUnitAnalysisManager::id<UnitFunctionCountAnalysis>()},
+ .Parameters = {},
+ .DeclaredChanges = {rcc::MachinePassChange::BlockLayout},
+ };
+ return Contract;
+ }
+
+ [[nodiscard]] rcc::Expected<rcc::CompilationUnitPassResult>
+ run(rcc::CompilationUnit &Unit, const rcc::TargetDescription &,
+ rcc::CompilationUnitAnalysisManager &, rcc::MachineFunctionAnalysisManager &) override {
+ auto Created = Unit.createMachineFunction("added-before-failure");
+ if (!Created)
+ return std::unexpected(Created.error());
+ return rcc::makeUnexpected(rcc::ErrorCode::VerificationError,
+ "intentional compilation-unit pass failure");
+ }
+};
+
+void testMachinePassManager(TestContext &Context, const rcc::TargetDescription &Target) {
+ auto Function = rcc::MachineFunction::create("pass", rcc::MachineFunctionStableID::fromValue(2));
+ Context.expect(Function.has_value(), "pass function creation must succeed");
+ if (!Function)
+ return;
+
+ rcc::MachineFunctionAnalysisManager Analyses;
+ Context.expect(Analyses
+ .registerAnalysis<BlockCountAnalysis>({
+ .Name = "BlockCount",
+ .Dependencies = {},
+ .InvalidatedBy = rcc::MachinePassChanges::all(),
+ .ThreadSafety = rcc::PassThreadSafety::ThreadSafe,
+ })
+ .has_value(),
+ "pass analysis registration must succeed");
+
+ rcc::MachineFunctionPassManager Pipeline;
+ Context.expect(Pipeline.addPass(std::make_unique<RequiredAnalysisPass>()).has_value(),
+ "a valid pass must be accepted");
+ auto Run = Pipeline.run(**Function, Target, Analyses);
+ Context.expect(Run.has_value(), "a pass with a materialized required analysis must run");
+
+ auto ChangedFunction =
+ rcc::MachineFunction::create("unreported", rcc::MachineFunctionStableID::fromValue(3));
+ rcc::MachineFunctionAnalysisManager EmptyAnalyses;
+ rcc::MachineFunctionPassManager Detecting(
+ {.VerifyBefore = true, .VerifyEach = true, .DetectUnreportedChanges = true});
+ Context.expect(ChangedFunction &&
+ Detecting.addPass(std::make_unique<UnreportedChangePass>()).has_value() &&
+ !Detecting.run(**ChangedFunction, Target, EmptyAnalyses),
+ "change detection must reject an unreported MachineIR mutation");
+
+ auto FailedFunction =
+ rcc::MachineFunction::create("failed", rcc::MachineFunctionStableID::fromValue(4));
+ rcc::MachineFunctionAnalysisManager FailureAnalyses;
+ Context.expect(FailedFunction && FailureAnalyses
+ .registerAnalysis<BlockCountAnalysis>({
+ .Name = "BlockCount",
+ .Dependencies = {},
+ .InvalidatedBy = rcc::MachinePassChanges::all(),
+ })
+ .has_value(),
+ "mutating failure analysis fixtures must be valid");
+ rcc::MachineFunctionPassManager FailingPipeline;
+ Context.expect(
+ FailedFunction &&
+ FailingPipeline.addPass(std::make_unique<MutatingFailurePass>()).has_value() &&
+ !FailingPipeline.run(**FailedFunction, Target, FailureAnalyses) &&
+ !FailureAnalyses.hasCached(**FailedFunction,
+ rcc::MachineFunctionAnalysisManager::id<BlockCountAnalysis>()),
+ "a pass that mutates and fails must not leave stale function analyses cached");
+}
+
+void testCompilationUnitAndParallelism(TestContext &Context, const rcc::TargetDescription &Target) {
+ rcc::CompilationUnit Unit;
+ for (std::size_t Index = 0; Index < 8; ++Index) {
+ auto Function = Unit.createMachineFunction("f" + std::to_string(Index));
+ Context.expect(Function.has_value(), "parallel test function creation must succeed");
+ }
+
+ std::atomic<std::uint32_t> Runs = 0;
+ rcc::MachineFunctionPassManager Parallel;
+ Context.expect(Parallel.addPass(std::make_unique<ParallelCountingPass>(Runs)).has_value(),
+ "thread-safe pass registration must succeed");
+ rcc::MachineFunctionAnalysisManager Prototype;
+ auto ParallelRun = Parallel.runFunctions(Unit, Target, Prototype, std::size_t{4});
+ Context.expect(ParallelRun.has_value() && Runs == Unit.functionCount(),
+ "parallel function execution must visit every function exactly once");
+
+ rcc::MachineFunctionAnalysisManager UnsafePrototype;
+ Context.expect(UnsafePrototype
+ .registerAnalysis<NonThreadSafeAnalysis>({
+ .Name = "NonThreadSafe",
+ .Dependencies = {},
+ .InvalidatedBy = rcc::MachinePassChanges::all(),
+ .ThreadSafety = rcc::PassThreadSafety::NotThreadSafe,
+ })
+ .has_value(),
+ "non-thread-safe analysis registration must be explicit");
+ rcc::MachineFunctionPassManager UnsafeParallel;
+ Context.expect(
+ UnsafeParallel.addPass(std::make_unique<RequiresNonThreadSafeAnalysisPass>()).has_value() &&
+ !UnsafeParallel.runFunctions(Unit, Target, UnsafePrototype, std::size_t{4}),
+ "parallel pipelines must reject a required analysis not marked thread-safe");
+
+ rcc::CompilationUnitAnalysisManager UnitAnalyses;
+ Context.expect(UnitAnalyses
+ .registerAnalysis<UnitFunctionCountAnalysis>({
+ .Name = "UnitFunctionCount",
+ .Dependencies = {},
+ .InvalidatedBy = rcc::MachinePassChanges::all(),
+ })
+ .has_value(),
+ "compilation-unit analysis registration must succeed");
+ rcc::MachineFunctionAnalysisManager FunctionAnalyses;
+ rcc::CompilationUnitPassManager UnitPipeline;
+ Context.expect(UnitPipeline.addPass(std::make_unique<ObserveUnitPass>()).has_value(),
+ "compilation-unit pass registration must succeed");
+ Context.expect(UnitPipeline.run(Unit, Target, UnitAnalyses, FunctionAnalyses).has_value(),
+ "compilation-unit pass and analysis must run through their own manager");
+
+ rcc::MachineFunction *FirstFunction = Unit.functionAt(0);
+ Context.expect(
+ FirstFunction != nullptr &&
+ FunctionAnalyses
+ .registerAnalysis<BlockCountAnalysis>({
+ .Name = "BlockCount",
+ .Dependencies = {},
+ .InvalidatedBy = rcc::MachinePassChanges::all(),
+ })
+ .has_value() &&
+ FunctionAnalyses.getResult<BlockCountAnalysis>(*FirstFunction, Target).has_value(),
+ "compilation-unit failure cache fixtures must materialize");
+ rcc::CompilationUnitPassManager FailingUnitPipeline;
+ Context.expect(
+ FirstFunction != nullptr &&
+ FailingUnitPipeline.addPass(std::make_unique<MutatingUnitFailurePass>()).has_value() &&
+ !FailingUnitPipeline.run(Unit, Target, UnitAnalyses, FunctionAnalyses) &&
+ !UnitAnalyses.hasCached(
+ Unit, rcc::CompilationUnitAnalysisManager::id<UnitFunctionCountAnalysis>()) &&
+ !FunctionAnalyses.hasCached(
+ *FirstFunction, rcc::MachineFunctionAnalysisManager::id<BlockCountAnalysis>()),
+ "a mutating compilation-unit failure must clear unit and function analysis caches");
+}
+
+} // namespace
+
+int main() {
+ TestContext Context;
+ auto Target = createTarget();
+ Context.expect(Target.has_value(), "machine pass tests require a valid target description");
+ if (!Target)
+ return Context.result();
+
+ testMachinePassManager(Context, *Target);
+ testCompilationUnitAndParallelism(Context, *Target);
+ return Context.result();
+}
diff --git a/backend/unittests/CodeGen/MachinePassTest.cpp b/backend/unittests/CodeGen/MachinePassTest.cpp
deleted file mode 100644
index fb125a4..0000000
--- a/backend/unittests/CodeGen/MachinePassTest.cpp
+++ /dev/null
@@ -1,918 +0,0 @@
-// SPDX-License-Identifier: GPL-3.0-or-later
-
-#include "rcc/CodeGen/MachinePass.h"
-
-#include "Target/TestTarget.h"
-#include "rcc/CodeGen/CompilationUnit.h"
-#include "rcc/CodeGen/GenericOpcodes.h"
-#include "rcc/CodeGen/MachineFunction.h"
-
-#include <algorithm>
-#include <atomic>
-#include <chrono>
-#include <cstddef>
-#include <cstdint>
-#include <iostream>
-#include <memory>
-#include <ranges>
-#include <string>
-#include <string_view>
-#include <thread>
-#include <utility>
-#include <vector>
-
-namespace {
-
-class TestContext final {
-public:
- void expect(bool Condition, std::string_view Message) {
- if (Condition)
- return;
- std::cerr << Message << '\n';
- ++Failures;
- }
-
- [[nodiscard]] int result() const noexcept {
- return Failures == 0 ? 0 : 1;
- }
-
-private:
- int Failures = 0;
-};
-
-[[nodiscard]] rcc::Expected<rcc::TargetDescription> createTarget() {
- std::vector<rcc::InstructionDescriptor> Descriptors;
- std::vector<rcc::ImmediatePredicate> Predicates;
- auto Appended = rcc::appendGenericInstructionInfo(Descriptors, Predicates);
- if (!Appended)
- return std::unexpected(Appended.error());
- auto Instructions = rcc::InstructionSet::create(std::move(Descriptors), std::move(Predicates));
- if (!Instructions)
- return std::unexpected(Instructions.error());
- return rcc::test::createTestTargetDescription(std::move(*Instructions));
-}
-
-class BlockCountAnalysis final {
-public:
- struct Result final {
- std::size_t Count = 0;
- };
-
- [[nodiscard]] static constexpr std::string_view name() noexcept {
- return "BlockCount";
- }
-
- [[nodiscard]] static rcc::Expected<Result> run(rcc::MachineFunction &Function,
- const rcc::TargetDescription &,
- rcc::MachineAnalysisManager &) {
- ++Runs;
- return Result{Function.blockCount()};
- }
-
- static inline std::atomic<std::uint32_t> Runs = 0;
-};
-
-class DependentAnalysis final {
-public:
- struct Result final {
- std::size_t Count = 0;
- };
-
- [[nodiscard]] static constexpr std::string_view name() noexcept {
- return "Dependent";
- }
-
- [[nodiscard]] static rcc::Expected<Result> run(rcc::MachineFunction &Function,
- const rcc::TargetDescription &Target,
- rcc::MachineAnalysisManager &Analyses) {
- auto Blocks = Analyses.getResult<BlockCountAnalysis>(Function, Target);
- if (!Blocks)
- return std::unexpected(Blocks.error());
- return Result{(*Blocks)->Count};
- }
-};
-
-class NonThreadSafeAnalysis final {
-public:
- struct Result final {};
-
- [[nodiscard]] static constexpr std::string_view name() noexcept {
- return "NonThreadSafe";
- }
-
- [[nodiscard]] static rcc::Expected<Result>
- run(rcc::MachineFunction &, const rcc::TargetDescription &, rcc::MachineAnalysisManager &) {
- return Result{};
- }
-};
-
-class FailingAnalysis final {
-public:
- struct Result final {};
-
- [[nodiscard]] static constexpr std::string_view name() noexcept {
- return "Failing";
- }
-
- [[nodiscard]] static rcc::Expected<Result>
- run(rcc::MachineFunction &, const rcc::TargetDescription &, rcc::MachineAnalysisManager &) {
- return rcc::makeUnexpected(rcc::ErrorCode::VerificationError,
- "intentional machine analysis failure");
- }
-};
-
-class StickyAnalysis final {
-public:
- struct Result final {
- [[nodiscard]] bool invalidate(const rcc::MachineFunction &,
- const rcc::PreservedAnalyses &) noexcept {
- return false;
- }
- };
-
- [[nodiscard]] static constexpr std::string_view name() noexcept {
- return "Sticky";
- }
- [[nodiscard]] static rcc::Expected<Result>
- run(rcc::MachineFunction &, const rcc::TargetDescription &, rcc::MachineAnalysisManager &) {
- return Result{};
- }
-};
-
-class ExpiringAnalysis final {
-public:
- struct Result final {
- [[nodiscard]] bool invalidate(const rcc::MachineFunction &,
- const rcc::PreservedAnalyses &) noexcept {
- return true;
- }
- };
-
- [[nodiscard]] static constexpr std::string_view name() noexcept {
- return "Expiring";
- }
- [[nodiscard]] static rcc::Expected<Result>
- run(rcc::MachineFunction &, const rcc::TargetDescription &, rcc::MachineAnalysisManager &) {
- return Result{};
- }
-};
-
-class CycleA final {
-public:
- struct Result final {};
- [[nodiscard]] static constexpr std::string_view name() noexcept {
- return "CycleA";
- }
- [[nodiscard]] static rcc::Expected<Result>
- run(rcc::MachineFunction &, const rcc::TargetDescription &, rcc::MachineAnalysisManager &) {
- return Result{};
- }
-};
-
-class CycleB final {
-public:
- struct Result final {};
- [[nodiscard]] static constexpr std::string_view name() noexcept {
- return "CycleB";
- }
- [[nodiscard]] static rcc::Expected<Result>
- run(rcc::MachineFunction &, const rcc::TargetDescription &, rcc::MachineAnalysisManager &) {
- return Result{};
- }
-};
-
-class RequiredAnalysisPass final : public rcc::MachineFunctionPass {
-public:
- [[nodiscard]] const rcc::MachinePassContract &contract() const noexcept override {
- static const rcc::MachinePassContract Contract{
- .Name = "RequiredAnalysis",
- .Requires = {},
- .Sets = {},
- .Clears = {},
- .RequiredAnalyses = {rcc::MachineAnalysisManager::id<DependentAnalysis>()},
- .VerificationStage = std::nullopt,
- };
- return Contract;
- }
-
- [[nodiscard]] rcc::Expected<rcc::MachinePassResult>
- run(rcc::MachineFunction &Function, const rcc::TargetDescription &Target,
- rcc::MachineAnalysisManager &Analyses) override {
- auto Dependent = Analyses.getResult<DependentAnalysis>(Function, Target);
- if (!Dependent)
- return std::unexpected(Dependent.error());
- auto FirstAction = Analyses.requestAction("first", Function);
- auto SecondAction = Analyses.requestAction("second", Function);
- if (!FirstAction || !SecondAction || !*FirstAction || *SecondAction) {
- return rcc::makeUnexpected(rcc::ErrorCode::VerificationError,
- "per-function action fuel was not enforced");
- }
- rcc::MachinePassResult Result;
- Result.Preserved = rcc::PreservedAnalyses::all();
- return Result;
- }
-};
-
-class UnreportedChangePass final : public rcc::MachineFunctionPass {
-public:
- [[nodiscard]] const rcc::MachinePassContract &contract() const noexcept override {
- static const rcc::MachinePassContract Contract{
- .Name = "UnreportedChange",
- .Requires = {},
- .Sets = {},
- .Clears = {},
- .RequiredAnalyses = {},
- .VerificationStage = std::nullopt,
- };
- return Contract;
- }
-
- [[nodiscard]] rcc::Expected<rcc::MachinePassResult> run(rcc::MachineFunction &Function,
- const rcc::TargetDescription &,
- rcc::MachineAnalysisManager &) override {
- auto Block = Function.createBasicBlock();
- if (!Block)
- return std::unexpected(Block.error());
- auto Appended = Function.appendBlock(**Block);
- if (!Appended)
- return std::unexpected(Appended.error());
- return rcc::MachinePassResult{};
- }
-};
-
-class RequiresFailingAnalysisPass final : public rcc::MachineFunctionPass {
-public:
- [[nodiscard]] const rcc::MachinePassContract &contract() const noexcept override {
- static const rcc::MachinePassContract Contract{
- .Name = "RequiresFailingAnalysis",
- .Requires = {},
- .Sets = {},
- .Clears = {},
- .RequiredAnalyses = {rcc::MachineAnalysisManager::id<FailingAnalysis>()},
- .VerificationStage = std::nullopt,
- };
- return Contract;
- }
-
- [[nodiscard]] rcc::Expected<rcc::MachinePassResult> run(rcc::MachineFunction &,
- const rcc::TargetDescription &,
- rcc::MachineAnalysisManager &) override {
- return rcc::MachinePassResult{};
- }
-};
-
-class MutatingFailurePass final : public rcc::MachineFunctionPass {
-public:
- [[nodiscard]] const rcc::MachinePassContract &contract() const noexcept override {
- static const rcc::MachinePassContract Contract{
- .Name = "MutatingFailure",
- .Requires = {},
- .Sets = {},
- .Clears = {},
- .RequiredAnalyses = {rcc::MachineAnalysisManager::id<BlockCountAnalysis>()},
- .VerificationStage = std::nullopt,
- };
- return Contract;
- }
-
- [[nodiscard]] rcc::Expected<rcc::MachinePassResult> run(rcc::MachineFunction &Function,
- const rcc::TargetDescription &,
- rcc::MachineAnalysisManager &) override {
- auto Block = Function.createBasicBlock();
- if (!Block)
- return std::unexpected(Block.error());
- auto Appended = Function.appendBlock(**Block);
- if (!Appended)
- return std::unexpected(Appended.error());
- return rcc::makeUnexpected(rcc::ErrorCode::VerificationError,
- "intentional mutating pass failure");
- }
-};
-
-class ParallelCountingPass final : public rcc::MachineFunctionPass {
-public:
- explicit ParallelCountingPass(std::atomic<std::uint32_t> &Count) : Count(&Count) {}
-
- [[nodiscard]] const rcc::MachinePassContract &contract() const noexcept override {
- static const rcc::MachinePassContract Contract = [] {
- rcc::MachinePassContract Value{
- .Name = "ParallelCounting",
- .Requires = {},
- .Sets = {},
- .Clears = {},
- .RequiredAnalyses = {},
- .VerificationStage = std::nullopt,
- };
- Value.ThreadSafety = rcc::PassThreadSafety::ThreadSafe;
- return Value;
- }();
- return Contract;
- }
-
- [[nodiscard]] rcc::Expected<rcc::MachinePassResult> run(rcc::MachineFunction &,
- const rcc::TargetDescription &,
- rcc::MachineAnalysisManager &) override {
- Count->fetch_add(1, std::memory_order_relaxed);
- return rcc::MachinePassResult{};
- }
-
-private:
- std::atomic<std::uint32_t> *Count;
-};
-
-class InstrumentedParallelPass final : public rcc::MachineFunctionPass {
-public:
- InstrumentedParallelPass(std::atomic<std::uint32_t> &Runs, std::atomic<std::uint32_t> &Active,
- std::atomic<std::uint32_t> &MaximumActive)
- : Runs(&Runs), Active(&Active), MaximumActive(&MaximumActive) {}
-
- [[nodiscard]] const rcc::MachinePassContract &contract() const noexcept override {
- static const rcc::MachinePassContract Contract = [] {
- rcc::MachinePassContract Value{
- .Name = "InstrumentedParallel",
- .Requires = {},
- .Sets = {},
- .Clears = {},
- .RequiredAnalyses = {},
- .VerificationStage = std::nullopt,
- };
- Value.ThreadSafety = rcc::PassThreadSafety::ThreadSafe;
- Value.DeclaredChanges = {rcc::MachinePassChange::BlockLayout};
- return Value;
- }();
- return Contract;
- }
-
- [[nodiscard]] rcc::Expected<rcc::MachinePassResult> run(rcc::MachineFunction &Function,
- const rcc::TargetDescription &,
- rcc::MachineAnalysisManager &) override {
- const std::uint32_t Current = Active->fetch_add(1, std::memory_order_acq_rel) + 1U;
- std::uint32_t Maximum = MaximumActive->load(std::memory_order_relaxed);
- while (Maximum < Current &&
- !MaximumActive->compare_exchange_weak(Maximum, Current, std::memory_order_relaxed)) {
- }
- std::this_thread::sleep_for(std::chrono::milliseconds(2));
- auto Block = Function.createBasicBlock();
- if (!Block) {
- Active->fetch_sub(1, std::memory_order_acq_rel);
- return std::unexpected(Block.error());
- }
- auto Appended = Function.appendBlock(**Block);
- Active->fetch_sub(1, std::memory_order_acq_rel);
- if (!Appended)
- return std::unexpected(Appended.error());
- Runs->fetch_add(1, std::memory_order_relaxed);
- rcc::MachinePassResult Result;
- Result.Changed = true;
- Result.Changes.add(rcc::MachinePassChange::BlockLayout);
- return Result;
- }
-
-private:
- std::atomic<std::uint32_t> *Runs;
- std::atomic<std::uint32_t> *Active;
- std::atomic<std::uint32_t> *MaximumActive;
-};
-
-class RequiresNonThreadSafeAnalysisPass final : public rcc::MachineFunctionPass {
-public:
- [[nodiscard]] const rcc::MachinePassContract &contract() const noexcept override {
- static const rcc::MachinePassContract Contract = [] {
- rcc::MachinePassContract Value{
- .Name = "RequiresNonThreadSafe",
- .Requires = {},
- .Sets = {},
- .Clears = {},
- .RequiredAnalyses =
- {
- rcc::MachineAnalysisManager::id<NonThreadSafeAnalysis>(),
- },
- .VerificationStage = std::nullopt,
- };
- Value.ThreadSafety = rcc::PassThreadSafety::ThreadSafe;
- return Value;
- }();
- return Contract;
- }
-
- [[nodiscard]] rcc::Expected<rcc::MachinePassResult> run(rcc::MachineFunction &,
- const rcc::TargetDescription &,
- rcc::MachineAnalysisManager &) override {
- return rcc::MachinePassResult{};
- }
-};
-
-class UnitFunctionCountAnalysis final {
-public:
- struct Result final {
- std::size_t Count = 0;
- };
- [[nodiscard]] static constexpr std::string_view name() noexcept {
- return "UnitFunctionCount";
- }
- [[nodiscard]] static rcc::Expected<Result> run(rcc::CompilationUnit &Unit,
- const rcc::TargetDescription &,
- rcc::CompilationUnitAnalysisManager &) {
- return Result{Unit.functionCount()};
- }
-};
-
-class FailingUnitAnalysis final {
-public:
- struct Result final {};
-
- [[nodiscard]] static constexpr std::string_view name() noexcept {
- return "FailingUnit";
- }
-
- [[nodiscard]] static rcc::Expected<Result> run(rcc::CompilationUnit &,
- const rcc::TargetDescription &,
- rcc::CompilationUnitAnalysisManager &) {
- return rcc::makeUnexpected(rcc::ErrorCode::VerificationError,
- "intentional compilation-unit analysis failure");
- }
-};
-
-class RequiresFailingUnitAnalysisPass final : public rcc::CompilationUnitPass {
-public:
- [[nodiscard]] const rcc::CompilationUnitPassContract &contract() const noexcept override {
- static const rcc::CompilationUnitPassContract Contract{
- .Name = "RequiresFailingUnitAnalysis",
- .RequiredAnalyses =
- {
- rcc::CompilationUnitAnalysisManager::id<FailingUnitAnalysis>(),
- },
- .Parameters = {},
- .DeclaredChanges = {},
- };
- return Contract;
- }
-
- [[nodiscard]] rcc::Expected<rcc::CompilationUnitPassResult>
- run(rcc::CompilationUnit &, const rcc::TargetDescription &, rcc::CompilationUnitAnalysisManager &,
- rcc::MachineAnalysisManager &) override {
- return rcc::CompilationUnitPassResult{};
- }
-};
-
-class ObserveUnitPass final : public rcc::CompilationUnitPass {
-public:
- [[nodiscard]] const rcc::CompilationUnitPassContract &contract() const noexcept override {
- static const rcc::CompilationUnitPassContract Contract{
- .Name = "ObserveUnit",
- .RequiredAnalyses = {rcc::CompilationUnitAnalysisManager::id<UnitFunctionCountAnalysis>()},
- .Parameters = {},
- .DeclaredChanges = {},
- };
- return Contract;
- }
-
- [[nodiscard]] rcc::Expected<rcc::CompilationUnitPassResult>
- run(rcc::CompilationUnit &Unit, const rcc::TargetDescription &Target,
- rcc::CompilationUnitAnalysisManager &Analyses, rcc::MachineAnalysisManager &) override {
- auto Count = Analyses.getResult<UnitFunctionCountAnalysis>(Unit, Target);
- if (!Count)
- return std::unexpected(Count.error());
- if ((*Count)->Count != Unit.functionCount()) {
- return rcc::makeUnexpected(rcc::ErrorCode::VerificationError,
- "unit analysis returned a stale function count");
- }
- return rcc::CompilationUnitPassResult{};
- }
-};
-
-class MutatingUnitFailurePass final : public rcc::CompilationUnitPass {
-public:
- [[nodiscard]] const rcc::CompilationUnitPassContract &contract() const noexcept override {
- static const rcc::CompilationUnitPassContract Contract{
- .Name = "MutatingUnitFailure",
- .RequiredAnalyses = {rcc::CompilationUnitAnalysisManager::id<UnitFunctionCountAnalysis>()},
- .Parameters = {},
- .DeclaredChanges = {rcc::MachinePassChange::BlockLayout},
- };
- return Contract;
- }
-
- [[nodiscard]] rcc::Expected<rcc::CompilationUnitPassResult>
- run(rcc::CompilationUnit &Unit, const rcc::TargetDescription &,
- rcc::CompilationUnitAnalysisManager &, rcc::MachineAnalysisManager &) override {
- auto Created = Unit.createMachineFunction("added-before-failure");
- if (!Created)
- return std::unexpected(Created.error());
- return rcc::makeUnexpected(rcc::ErrorCode::VerificationError,
- "intentional compilation-unit pass failure");
- }
-};
-
-void testAnalysisInfrastructure(TestContext &Context, const rcc::TargetDescription &Target) {
- auto Function =
- rcc::MachineFunction::create("analysis", rcc::MachineFunctionStableID::fromValue(1));
- Context.expect(Function.has_value(), "analysis function creation must succeed");
- if (!Function)
- return;
-
- rcc::MachineAnalysisManager Analyses;
- Context.expect(Analyses
- .registerAnalysis<BlockCountAnalysis>({
- .Name = "BlockCount",
- .Dependencies = {},
- .InvalidatedBy = {rcc::MachinePassChange::CFG},
- })
- .has_value(),
- "base analysis registration must succeed");
- Context.expect(Analyses
- .registerAnalysis<DependentAnalysis>({
- .Name = "Dependent",
- .Dependencies = {rcc::MachineAnalysisManager::id<BlockCountAnalysis>()},
- .InvalidatedBy = {rcc::MachinePassChange::Operands},
- })
- .has_value(),
- "dependent analysis registration must succeed");
-
- BlockCountAnalysis::Runs = 0;
- auto First = Analyses.getResult<DependentAnalysis>(**Function, Target);
- auto Second = Analyses.getResult<DependentAnalysis>(**Function, Target);
- Context.expect(First && Second && *First == *Second && BlockCountAnalysis::Runs == 1,
- "analysis dependencies must materialize once and then use the cache");
-
- Analyses.invalidate(**Function, rcc::PreservedAnalyses::none(),
- {rcc::MachinePassChange::Registers});
- Context.expect(Analyses.cachedResultCount(**Function) == 2,
- "unrelated changes must preserve cached analyses precisely");
- Analyses.invalidate(**Function, rcc::PreservedAnalyses::none(), {rcc::MachinePassChange::CFG});
- Context.expect(Analyses.cachedResultCount(**Function) == 0,
- "invalidating a dependency must invalidate its dependent analysis");
-
- rcc::MachineAnalysisManager Cyclic;
- Context.expect(Cyclic
- .registerAnalysis<CycleA>({
- .Name = "CycleA",
- .Dependencies = {rcc::MachineAnalysisManager::id<CycleB>()},
- })
- .has_value() &&
- Cyclic
- .registerAnalysis<CycleB>({
- .Name = "CycleB",
- .Dependencies = {rcc::MachineAnalysisManager::id<CycleA>()},
- })
- .has_value(),
- "cyclic analysis registrations must be accepted until requested");
- Context.expect(!Cyclic.getResult<CycleA>(**Function, Target),
- "analysis dependency cycles must produce a structured error");
-
- rcc::MachineAnalysisManager CustomInvalidation;
- Context.expect(CustomInvalidation
- .registerAnalysis<StickyAnalysis>({
- .Name = "Sticky",
- .Dependencies = {},
- .InvalidatedBy = {rcc::MachinePassChange::CFG},
- })
- .has_value() &&
- CustomInvalidation
- .registerAnalysis<ExpiringAnalysis>({
- .Name = "Expiring",
- .Dependencies = {},
- .InvalidatedBy = {rcc::MachinePassChange::CFG},
- })
- .has_value() &&
- CustomInvalidation.getResult<StickyAnalysis>(**Function, Target) &&
- CustomInvalidation.getResult<ExpiringAnalysis>(**Function, Target),
- "custom invalidation analyses must materialize");
- CustomInvalidation.invalidate(**Function, rcc::PreservedAnalyses::none(),
- {rcc::MachinePassChange::CFG});
- Context.expect(
- CustomInvalidation.hasCached(**Function, rcc::MachineAnalysisManager::id<StickyAnalysis>()) &&
- !CustomInvalidation.hasCached(**Function,
- rcc::MachineAnalysisManager::id<ExpiringAnalysis>()),
- "analysis invalidate() must return false to preserve and true to invalidate");
-}
-
-void testPassAndInstrumentation(TestContext &Context, const rcc::TargetDescription &Target) {
- auto Function = rcc::MachineFunction::create("pass", rcc::MachineFunctionStableID::fromValue(2));
- Context.expect(Function.has_value(), "pass function creation must succeed");
- if (!Function)
- return;
-
- rcc::MachineAnalysisManager Analyses;
- Context.expect(
- Analyses
- .registerAnalysis<BlockCountAnalysis>({
- .Name = "BlockCount",
- .Dependencies = {},
- .InvalidatedBy = rcc::MachinePassChanges::all(),
- .ThreadSafety = rcc::PassThreadSafety::ThreadSafe,
- })
- .has_value() &&
- Analyses
- .registerAnalysis<DependentAnalysis>({
- .Name = "Dependent",
- .Dependencies = {rcc::MachineAnalysisManager::id<BlockCountAnalysis>()},
- })
- .has_value(),
- "pass analysis registrations must succeed");
-
- rcc::MachinePassInstrumentation Instrumentation;
- Instrumentation.setPerFunctionFuel(1);
- std::uint32_t BeforePass = 0;
- std::uint32_t AfterPass = 0;
- std::uint32_t BeforeAnalysis = 0;
- std::uint32_t AfterAnalysis = 0;
- std::uint32_t AnalysisCacheHits = 0;
- std::uint32_t Printed = 0;
- std::uint32_t ChangeEvents = 0;
- std::uint32_t FailureEvents = 0;
- Instrumentation.addBeforeCallback(
- [&BeforePass](std::string_view, const rcc::MachineFunction &) { ++BeforePass; });
- Instrumentation.addAfterCallback([&AfterPass](std::string_view, const rcc::MachineFunction &,
- const rcc::MachinePassResult &) { ++AfterPass; });
- Instrumentation.addBeforeAnalysisCallback(
- [&BeforeAnalysis](std::string_view, const rcc::MachineFunction &) { ++BeforeAnalysis; });
- Instrumentation.addAfterAnalysisCallback(
- [&AfterAnalysis, &AnalysisCacheHits](std::string_view, const rcc::MachineFunction &,
- bool CacheHit, std::uint64_t) {
- ++AfterAnalysis;
- AnalysisCacheHits += CacheHit ? 1U : 0U;
- });
- Instrumentation.addIRPrintCallback([&Printed](rcc::InstrumentationPhase, std::string_view,
- const rcc::MachineFunction &) { ++Printed; });
- Instrumentation.addChangeCallback([&ChangeEvents](std::string_view, const rcc::MachineFunction &,
- rcc::MachinePassChanges Changes,
- bool FingerprintChanged) {
- if (Changes.empty() && !FingerprintChanged)
- ++ChangeEvents;
- });
- Instrumentation.addFailureCallback([&FailureEvents](std::string_view,
- const rcc::MachineFunction &,
- const rcc::Error &) { ++FailureEvents; });
-
- rcc::MachinePassManager Pipeline;
- Context.expect(Pipeline.addPass(std::make_unique<RequiredAnalysisPass>()).has_value(),
- "a valid pass must be accepted");
- auto Run = Pipeline.run(**Function, Target, Analyses, &Instrumentation);
- Context.expect(Run.has_value(), "a pass with a materialized required analysis must run");
- Context.expect(BeforePass == 1 && AfterPass == 1 && BeforeAnalysis == 2 && AfterAnalysis == 4 &&
- AnalysisCacheHits == 2 && Printed == 2 && ChangeEvents == 1,
- "pass, analysis, cache-hit, IR-print, and change callbacks must all run");
- const auto Statistics = Instrumentation.statistics();
- Context.expect(Statistics.size() == 3,
- "instrumentation must collect one pass and two analysis statistics");
-
- auto ChangedFunction =
- rcc::MachineFunction::create("unreported", rcc::MachineFunctionStableID::fromValue(3));
- rcc::MachineAnalysisManager EmptyAnalyses;
- rcc::MachinePassManager Detecting(
- {.VerifyBefore = true, .VerifyEach = true, .DetectUnreportedChanges = true});
- Context.expect(ChangedFunction &&
- Detecting.addPass(std::make_unique<UnreportedChangePass>()).has_value() &&
- !Detecting.run(**ChangedFunction, Target, EmptyAnalyses, &Instrumentation) &&
- FailureEvents == 1,
- "change detection must reject an unreported MachineIR mutation");
-
- auto FailedFunction =
- rcc::MachineFunction::create("failed", rcc::MachineFunctionStableID::fromValue(4));
- rcc::MachineAnalysisManager FailureAnalyses;
- Context.expect(FailedFunction && FailureAnalyses
- .registerAnalysis<BlockCountAnalysis>({
- .Name = "BlockCount",
- .Dependencies = {},
- .InvalidatedBy = rcc::MachinePassChanges::all(),
- })
- .has_value(),
- "mutating failure analysis fixtures must be valid");
- rcc::MachinePassManager FailingPipeline;
- Context.expect(FailedFunction &&
- FailingPipeline.addPass(std::make_unique<MutatingFailurePass>()).has_value() &&
- !FailingPipeline.run(**FailedFunction, Target, FailureAnalyses) &&
- !FailureAnalyses.hasCached(
- **FailedFunction, rcc::MachineAnalysisManager::id<BlockCountAnalysis>()),
- "a pass that mutates and fails must not leave stale function analyses cached");
-
- rcc::MachineAnalysisManager FailingAnalyses;
- Context.expect(FailingAnalyses
- .registerAnalysis<FailingAnalysis>({
- .Name = "Failing",
- .Dependencies = {},
- })
- .has_value(),
- "failing analysis registration must succeed");
- rcc::MachinePassInstrumentation FailureInstrumentation;
- std::uint32_t BeforeFailingAnalysis = 0;
- std::uint32_t FailingAnalysisEvents = 0;
- std::uint32_t RequiredAnalysisPassFailures = 0;
- FailureInstrumentation.addBeforeAnalysisCallback(
- [&BeforeFailingAnalysis](std::string_view, const rcc::MachineFunction &) {
- ++BeforeFailingAnalysis;
- });
- FailureInstrumentation.addAnalysisFailureCallback(
- [&FailingAnalysisEvents](std::string_view, const rcc::MachineFunction &, const rcc::Error &) {
- ++FailingAnalysisEvents;
- });
- FailureInstrumentation.addFailureCallback(
- [&RequiredAnalysisPassFailures](std::string_view, const rcc::MachineFunction &,
- const rcc::Error &) { ++RequiredAnalysisPassFailures; });
- rcc::MachinePassManager RequiredAnalysisFailurePipeline;
- Context.expect(
- RequiredAnalysisFailurePipeline.addPass(std::make_unique<RequiresFailingAnalysisPass>())
- .has_value() &&
- !RequiredAnalysisFailurePipeline.run(**Function, Target, FailingAnalyses,
- &FailureInstrumentation) &&
- BeforeFailingAnalysis == 1 && FailingAnalysisEvents == 1 &&
- RequiredAnalysisPassFailures == 1,
- "analysis and pass failure instrumentation must report required-analysis failures");
-}
-
-void testCompilationUnitAndParallelism(TestContext &Context, const rcc::TargetDescription &Target) {
- rcc::CompilationUnit Unit;
- for (std::size_t Index = 0; Index < 8; ++Index) {
- auto Function = Unit.createMachineFunction("f" + std::to_string(Index));
- Context.expect(Function.has_value(), "parallel test function creation must succeed");
- }
-
- std::atomic<std::uint32_t> Runs = 0;
- rcc::MachinePassManager Parallel;
- Context.expect(Parallel.addPass(std::make_unique<ParallelCountingPass>(Runs)).has_value(),
- "thread-safe pass registration must succeed");
- rcc::MachineAnalysisManager Prototype;
- auto ParallelRun = Parallel.runFunctions(Unit, Target, Prototype, 4);
- Context.expect(ParallelRun.has_value() && Runs == Unit.functionCount(),
- "parallel function execution must visit every function exactly once");
-
- std::atomic<std::uint32_t> DuplicateRuns = 0;
- rcc::MachinePassManager Repeated;
- Context.expect(
- Repeated.addPass(std::make_unique<ParallelCountingPass>(DuplicateRuns)).has_value() &&
- Repeated.addPass(std::make_unique<ParallelCountingPass>(DuplicateRuns)).has_value() &&
- Repeated.runFunctions(Unit, Target, Prototype, 4).has_value() &&
- DuplicateRuns == Unit.functionCount() * 2,
- "a pipeline must allow the same named pass to run more than once");
-
- rcc::MachinePassInstrumentation Instrumentation;
- std::vector<std::string> ObservedFunctions;
- std::vector<std::size_t> BeforeBlockCounts;
- std::vector<std::size_t> AfterBlockCounts;
- Instrumentation.addBeforeCallback([&ObservedFunctions, &BeforeBlockCounts](
- std::string_view, const rcc::MachineFunction &Function) {
- ObservedFunctions.emplace_back(Function.name());
- BeforeBlockCounts.push_back(Function.blockCount());
- });
- Instrumentation.addAfterCallback([&AfterBlockCounts](std::string_view,
- const rcc::MachineFunction &Function,
- const rcc::MachinePassResult &) {
- AfterBlockCounts.push_back(Function.blockCount());
- });
- std::atomic<std::uint32_t> InstrumentedRuns = 0;
- std::atomic<std::uint32_t> ActiveRuns = 0;
- std::atomic<std::uint32_t> MaximumActiveRuns = 0;
- rcc::MachinePassManager Instrumented;
- Context.expect(
- Instrumented
- .addPass(std::make_unique<InstrumentedParallelPass>(InstrumentedRuns, ActiveRuns,
- MaximumActiveRuns))
- .has_value() &&
- Instrumented.runFunctions(Unit, Target, Prototype, 4, &Instrumentation).has_value() &&
- InstrumentedRuns == Unit.functionCount() && MaximumActiveRuns > 1,
- "instrumented function pipelines must execute concurrently with a parallel request");
- bool StableCallbackOrder = ObservedFunctions.size() == Unit.functionCount();
- for (std::size_t Index = 0; StableCallbackOrder && Index < ObservedFunctions.size(); ++Index)
- StableCallbackOrder = ObservedFunctions[Index] == "f" + std::to_string(Index);
- Context.expect(StableCallbackOrder,
- "instrumentation callbacks must commit in stable compilation-unit order");
- Context.expect(
- BeforeBlockCounts.size() == Unit.functionCount() &&
- AfterBlockCounts.size() == Unit.functionCount() &&
- std::ranges::all_of(BeforeBlockCounts, [](std::size_t Count) { return Count == 0; }) &&
- std::ranges::all_of(AfterBlockCounts, [](std::size_t Count) { return Count == 1; }),
- "buffered instrumentation must retain distinct before/after IR snapshots");
-
- rcc::MachineAnalysisManager UnsafePrototype;
- Context.expect(UnsafePrototype
- .registerAnalysis<NonThreadSafeAnalysis>({
- .Name = "NonThreadSafe",
- .Dependencies = {},
- .InvalidatedBy = rcc::MachinePassChanges::all(),
- .ThreadSafety = rcc::PassThreadSafety::NotThreadSafe,
- })
- .has_value(),
- "non-thread-safe analysis registration must be explicit");
- rcc::MachinePassManager UnsafeParallel;
- Context.expect(
- UnsafeParallel.addPass(std::make_unique<RequiresNonThreadSafeAnalysisPass>()).has_value() &&
- !UnsafeParallel.runFunctions(Unit, Target, UnsafePrototype, 4),
- "parallel pipelines must reject a required analysis not marked thread-safe");
-
- rcc::CompilationUnitAnalysisManager UnitAnalyses;
- Context.expect(UnitAnalyses
- .registerAnalysis<UnitFunctionCountAnalysis>({
- .Name = "UnitFunctionCount",
- .Dependencies = {},
- .InvalidatedBy = rcc::MachinePassChanges::all(),
- })
- .has_value(),
- "compilation-unit analysis registration must succeed");
- rcc::MachineAnalysisManager FunctionAnalyses;
- rcc::CompilationUnitPassManager UnitPipeline;
- Context.expect(UnitPipeline.addPass(std::make_unique<ObserveUnitPass>()).has_value(),
- "compilation-unit pass registration must succeed");
- rcc::MachinePassInstrumentation UnitInstrumentation;
- std::uint32_t BeforeUnit = 0;
- std::uint32_t AfterUnit = 0;
- std::uint32_t BeforeUnitAnalysis = 0;
- std::uint32_t AfterUnitAnalysis = 0;
- std::uint32_t UnitAnalysisCacheHits = 0;
- UnitInstrumentation.addBeforeUnitCallback(
- [&BeforeUnit](std::string_view, const rcc::CompilationUnit &) { ++BeforeUnit; });
- UnitInstrumentation.addAfterUnitCallback(
- [&AfterUnit](std::string_view, const rcc::CompilationUnit &,
- const rcc::CompilationUnitPassResult &) { ++AfterUnit; });
- UnitInstrumentation.addBeforeUnitAnalysisCallback(
- [&BeforeUnitAnalysis](std::string_view, const rcc::CompilationUnit &) {
- ++BeforeUnitAnalysis;
- });
- UnitInstrumentation.addAfterUnitAnalysisCallback(
- [&AfterUnitAnalysis, &UnitAnalysisCacheHits](std::string_view, const rcc::CompilationUnit &,
- bool CacheHit, std::uint64_t) {
- ++AfterUnitAnalysis;
- UnitAnalysisCacheHits += CacheHit ? 1U : 0U;
- });
- Context.expect(
- UnitPipeline.run(Unit, Target, UnitAnalyses, FunctionAnalyses, &UnitInstrumentation)
- .has_value(),
- "compilation-unit pass and analysis must run through their own manager");
- Context.expect(BeforeUnit == 1 && AfterUnit == 1 && BeforeUnitAnalysis == 1 &&
- AfterUnitAnalysis == 2 && UnitAnalysisCacheHits == 1,
- "compilation-unit instrumentation must report pass and analysis cache events");
-
- rcc::CompilationUnitAnalysisManager FailingUnitAnalyses;
- Context.expect(FailingUnitAnalyses
- .registerAnalysis<FailingUnitAnalysis>({
- .Name = "FailingUnit",
- .Dependencies = {},
- })
- .has_value(),
- "failing compilation-unit analysis registration must succeed");
- rcc::CompilationUnitPassManager FailingUnitAnalysisPipeline;
- Context.expect(
- FailingUnitAnalysisPipeline.addPass(std::make_unique<RequiresFailingUnitAnalysisPass>())
- .has_value(),
- "a pass requiring a failing unit analysis must register");
- rcc::MachinePassInstrumentation FailingUnitInstrumentation;
- std::uint32_t BeforeFailingUnitAnalysis = 0;
- std::uint32_t FailingUnitAnalysisEvents = 0;
- std::uint32_t RequiredUnitAnalysisPassFailures = 0;
- FailingUnitInstrumentation.addBeforeUnitAnalysisCallback(
- [&BeforeFailingUnitAnalysis](std::string_view, const rcc::CompilationUnit &) {
- ++BeforeFailingUnitAnalysis;
- });
- FailingUnitInstrumentation.addUnitAnalysisFailureCallback(
- [&FailingUnitAnalysisEvents](std::string_view, const rcc::CompilationUnit &,
- const rcc::Error &) { ++FailingUnitAnalysisEvents; });
- FailingUnitInstrumentation.addUnitFailureCallback(
- [&RequiredUnitAnalysisPassFailures](std::string_view, const rcc::CompilationUnit &,
- const rcc::Error &) {
- ++RequiredUnitAnalysisPassFailures;
- });
- Context.expect(
- !FailingUnitAnalysisPipeline.run(Unit, Target, FailingUnitAnalyses, FunctionAnalyses,
- &FailingUnitInstrumentation) &&
- BeforeFailingUnitAnalysis == 1 && FailingUnitAnalysisEvents == 1 &&
- RequiredUnitAnalysisPassFailures == 1,
- "unit analysis and pass failure instrumentation must report required-analysis failures");
-
- rcc::MachineFunction *FirstFunction = Unit.functionAt(0);
- Context.expect(
- FirstFunction != nullptr &&
- FunctionAnalyses
- .registerAnalysis<BlockCountAnalysis>({
- .Name = "BlockCount",
- .Dependencies = {},
- .InvalidatedBy = rcc::MachinePassChanges::all(),
- })
- .has_value() &&
- FunctionAnalyses.getResult<BlockCountAnalysis>(*FirstFunction, Target).has_value(),
- "compilation-unit failure cache fixtures must materialize");
- rcc::CompilationUnitPassManager FailingUnitPipeline;
- Context.expect(
- FirstFunction != nullptr &&
- FailingUnitPipeline.addPass(std::make_unique<MutatingUnitFailurePass>()).has_value() &&
- !FailingUnitPipeline.run(Unit, Target, UnitAnalyses, FunctionAnalyses) &&
- !UnitAnalyses.hasCached(
- Unit, rcc::CompilationUnitAnalysisManager::id<UnitFunctionCountAnalysis>()) &&
- !FunctionAnalyses.hasCached(*FirstFunction,
- rcc::MachineAnalysisManager::id<BlockCountAnalysis>()),
- "a mutating compilation-unit failure must clear unit and function analysis caches");
-}
-
-} // namespace
-
-int main() {
- TestContext Context;
- auto Target = createTarget();
- Context.expect(Target.has_value(), "machine pass tests require a valid target description");
- if (!Target)
- return Context.result();
-
- testAnalysisInfrastructure(Context, *Target);
- testPassAndInstrumentation(Context, *Target);
- testCompilationUnitAndParallelism(Context, *Target);
- return Context.result();
-}
diff --git a/backend/unittests/CodeGen/MachineSchedulingTest.cpp b/backend/unittests/CodeGen/MachineSchedulingTest.cpp
index bcd4100..5162fb8 100644
--- a/backend/unittests/CodeGen/MachineSchedulingTest.cpp
+++ b/backend/unittests/CodeGen/MachineSchedulingTest.cpp
@@ -386,7 +386,7 @@ void testTargetSchedulingHooks(TestContext &Context, const rcc::TargetDescriptio
Context.expect(false, "target scheduling preference model must be created");
return;
}
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
rcc::MachineSchedulerPass PreferencePass(
*PreferenceModel, {.MaximumRegionSize = 8, .EnableBidirectionalScheduling = false});
auto Preferred = PreferencePass.run(*Fixture.Function, Target, Analyses);
@@ -408,7 +408,7 @@ void testTargetSchedulingHooks(TestContext &Context, const rcc::TargetDescriptio
rcc::MachineInstr *BoundaryFirst =
buildADDI(Context, BoundaryBuilder, makeGPR(Context, *BoundaryFixture.Function), X0, 1);
(void)buildADDI(Context, BoundaryBuilder, makeGPR(Context, *BoundaryFixture.Function), X0, 2);
- rcc::MachineAnalysisManager BoundaryAnalyses;
+ rcc::MachineFunctionAnalysisManager BoundaryAnalyses;
rcc::MachineSchedulerPass BoundaryPass(
*BoundaryModel, {.MaximumRegionSize = 8, .EnableBidirectionalScheduling = false});
auto BoundaryResult = BoundaryPass.run(*BoundaryFixture.Function, Target, BoundaryAnalyses);
@@ -455,7 +455,7 @@ void testPreRAScheduler(TestContext &Context, const rcc::TargetDescription &Targ
buildSchedulingChain(Context, Fixture, Target, false, Short, Long);
Context.expect(Fixture.Block->firstInstruction() == Short,
"pre-RA fixture must begin in intentionally suboptimal order");
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
rcc::MachineSchedulerPass Pass(rcc::riscv::schedulingModel(),
{.MaximumRegionSize = 64, .EnableBidirectionalScheduling = false});
auto Result = Pass.run(*Fixture.Function, Target, Analyses);
@@ -482,7 +482,7 @@ void testPostRASchedulerAndLivenessRepair(TestContext &Context,
if (!Rebuilt)
return;
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
rcc::PostRASchedulerPass Pass(rcc::riscv::schedulingModel(),
{.MaximumRegionSize = 64, .EnableBidirectionalScheduling = false});
auto Result = Pass.run(*Fixture.Function, Target, Analyses);
diff --git a/backend/unittests/CodeGen/PHIEliminationTest.cpp b/backend/unittests/CodeGen/PHIEliminationTest.cpp
index 00668e4..9bc9a57 100644
--- a/backend/unittests/CodeGen/PHIEliminationTest.cpp
+++ b/backend/unittests/CodeGen/PHIEliminationTest.cpp
@@ -4,7 +4,7 @@
#include "SSAExitTestSupport.h"
#include "rcc/CodeGen/MachineCFGUpdater.h"
-#include "rcc/CodeGen/MachinePass.h"
+#include "rcc/CodeGen/MachinePassManager.h"
#include "rcc/CodeGen/MachineVerifier.h"
#include <array>
@@ -62,11 +62,11 @@ buildPhi(rcc::MachineFunction &Function, const rcc::TargetDescription &Target,
[[nodiscard]] rcc::Expected<void> runPHIElimination(rcc::MachineFunction &Function,
const rcc::TargetDescription &Target,
const rcc::TargetInstrInfo &Info) {
- rcc::MachinePassManager Pipeline;
+ rcc::MachineFunctionPassManager Pipeline;
auto Added = Pipeline.addPass(std::make_unique<rcc::PHIEliminationPass>(Info));
if (!Added)
return std::unexpected(Added.error());
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
return Pipeline.run(Function, Target, Analyses);
}
@@ -391,7 +391,7 @@ void testUndefAndFailureAtomicity(TestContext &Context, const rcc::TargetDescrip
const std::size_t RegistersBefore = Atomic.Function->registerInfo().virtualRegisters().size();
const std::uint64_t PropertiesBefore = Atomic.Function->properties().rawValue();
TestInstrInfo RejectingInfo(true);
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
rcc::PHIEliminationPass FailingPass(RejectingInfo);
auto Failed = FailingPass.run(*Atomic.Function, Target, Analyses);
Context.expect(!Failed && Failed.error().code() == rcc::ErrorCode::Unsupported,
diff --git a/backend/unittests/CodeGen/PassInstrumentationTest.cpp b/backend/unittests/CodeGen/PassInstrumentationTest.cpp
new file mode 100644
index 0000000..97ce445
--- /dev/null
+++ b/backend/unittests/CodeGen/PassInstrumentationTest.cpp
@@ -0,0 +1,173 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "Target/TestTarget.h"
+#include "rcc/CodeGen/GenericOpcodes.h"
+#include "rcc/CodeGen/MachineFunction.h"
+#include "rcc/CodeGen/MachinePassManager.h"
+
+#include <cstddef>
+#include <cstdint>
+#include <iostream>
+#include <memory>
+#include <string_view>
+#include <utility>
+#include <vector>
+
+namespace {
+
+class TestContext final {
+public:
+ void expect(bool Condition, std::string_view Message) {
+ if (Condition)
+ return;
+ std::cerr << Message << '\n';
+ ++Failures;
+ }
+
+ [[nodiscard]] int result() const noexcept {
+ return Failures == 0 ? 0 : 1;
+ }
+
+private:
+ int Failures = 0;
+};
+
+[[nodiscard]] rcc::Expected<rcc::TargetDescription> createTarget() {
+ std::vector<rcc::InstructionDescriptor> Descriptors;
+ std::vector<rcc::ImmediatePredicate> Predicates;
+ auto Appended = rcc::appendGenericInstructionInfo(Descriptors, Predicates);
+ if (!Appended)
+ return std::unexpected(Appended.error());
+ auto Instructions = rcc::InstructionSet::create(std::move(Descriptors), std::move(Predicates));
+ if (!Instructions)
+ return std::unexpected(Instructions.error());
+ return rcc::test::createTestTargetDescription(std::move(*Instructions));
+}
+
+class BlockCountAnalysis final {
+public:
+ struct Result final {
+ std::size_t Count = 0;
+ };
+
+ [[nodiscard]] static constexpr std::string_view name() noexcept {
+ return "BlockCount";
+ }
+
+ [[nodiscard]] static rcc::Expected<Result> run(rcc::MachineFunction &Function,
+ const rcc::TargetDescription &,
+ rcc::MachineFunctionAnalysisManager &) {
+ return Result{Function.blockCount()};
+ }
+};
+
+class InstrumentedPass final : public rcc::MachineFunctionPass {
+public:
+ [[nodiscard]] const rcc::MachinePassContract &contract() const noexcept override {
+ static const rcc::MachinePassContract Contract{
+ .Name = "Instrumented",
+ .Requires = {},
+ .Sets = {},
+ .Clears = {},
+ .RequiredAnalyses =
+ {
+ rcc::MachineFunctionAnalysisManager::id<BlockCountAnalysis>(),
+ },
+ .VerificationStage = std::nullopt,
+ };
+ return Contract;
+ }
+
+ [[nodiscard]] rcc::Expected<rcc::MachinePassResult>
+ run(rcc::MachineFunction &Function, const rcc::TargetDescription &Target,
+ rcc::MachineFunctionAnalysisManager &Analyses) override {
+ auto First = Analyses.getResult<BlockCountAnalysis>(Function, Target);
+ auto Second = Analyses.getResult<BlockCountAnalysis>(Function, Target);
+ auto FirstAction = Analyses.requestAction("first", Function);
+ auto SecondAction = Analyses.requestAction("second", Function);
+ if (!First || !Second || !FirstAction || !SecondAction || !*FirstAction || *SecondAction)
+ return rcc::makeUnexpected(rcc::ErrorCode::VerificationError,
+ "instrumentation action policy was not enforced");
+ rcc::MachinePassResult Result;
+ Result.Preserved = rcc::PreservedAnalyses::all();
+ return Result;
+ }
+};
+
+void testInstrumentation(TestContext &Context, const rcc::TargetDescription &Target) {
+ auto Function =
+ rcc::MachineFunction::create("instrumentation", rcc::MachineFunctionStableID::fromValue(1));
+ Context.expect(Function.has_value(), "instrumentation function creation must succeed");
+ if (!Function)
+ return;
+
+ rcc::MachineFunctionAnalysisManager Analyses;
+ Context.expect(Analyses
+ .registerAnalysis<BlockCountAnalysis>({
+ .Name = "BlockCount",
+ .Dependencies = {},
+ .InvalidatedBy = rcc::MachinePassChanges::all(),
+ .ThreadSafety = rcc::PassThreadSafety::ThreadSafe,
+ })
+ .has_value(),
+ "instrumentation analysis registration must succeed");
+
+ rcc::MachinePassInstrumentation Instrumentation;
+ Instrumentation.setPerFunctionFuel(1);
+ std::uint32_t BeforePass = 0;
+ std::uint32_t AfterPass = 0;
+ std::uint32_t BeforeAnalysis = 0;
+ std::uint32_t AfterAnalysis = 0;
+ std::uint32_t CacheHits = 0;
+ std::uint32_t Printed = 0;
+ std::uint32_t Changes = 0;
+ Instrumentation.addBeforeCallback(
+ [&BeforePass](std::string_view, const rcc::MachineFunction &) { ++BeforePass; });
+ Instrumentation.addAfterCallback([&AfterPass](std::string_view, const rcc::MachineFunction &,
+ const rcc::MachinePassResult &) { ++AfterPass; });
+ Instrumentation.addBeforeAnalysisCallback(
+ [&BeforeAnalysis](std::string_view, const rcc::MachineFunction &) { ++BeforeAnalysis; });
+ Instrumentation.addAfterAnalysisCallback(
+ [&AfterAnalysis, &CacheHits](std::string_view, const rcc::MachineFunction &, bool CacheHit,
+ std::uint64_t) {
+ ++AfterAnalysis;
+ CacheHits += CacheHit ? 1U : 0U;
+ });
+ Instrumentation.addIRPrintCallback([&Printed](rcc::InstrumentationPhase, std::string_view,
+ const rcc::MachineFunction &) { ++Printed; });
+ Instrumentation.addChangeCallback([&Changes](std::string_view, const rcc::MachineFunction &,
+ rcc::MachinePassChanges ReportedChanges,
+ bool FingerprintChanged) {
+ if (ReportedChanges.empty() && !FingerprintChanged)
+ ++Changes;
+ });
+
+ rcc::MachineFunctionPassManager Pipeline;
+ Context.expect(Pipeline.addPass(std::make_unique<InstrumentedPass>()).has_value() &&
+ Pipeline.run(**Function, Target, Analyses, &Instrumentation).has_value(),
+ "instrumented pass must run");
+ Context.expect(BeforePass == 1 && AfterPass == 1 && BeforeAnalysis == 1 && AfterAnalysis == 3 &&
+ CacheHits == 2 && Printed == 2 && Changes == 1,
+ "all pass and analysis instrumentation points must run");
+
+ const auto Events = Instrumentation.actionEvents();
+ Context.expect(Events.size() == 2 && Events[0].Accepted && !Events[1].Accepted,
+ "action instrumentation must record accepted and rejected decisions");
+ const auto Statistics = Instrumentation.statistics();
+ Context.expect(Statistics.size() == 2,
+ "instrumentation must collect one pass and one analysis statistic");
+}
+
+} // namespace
+
+int main() {
+ TestContext Context;
+ auto Target = createTarget();
+ Context.expect(Target.has_value(),
+ "pass instrumentation tests require a valid target description");
+ if (!Target)
+ return Context.result();
+
+ testInstrumentation(Context, *Target);
+ return Context.result();
+}
diff --git a/backend/unittests/CodeGen/PassManagerTest.cpp b/backend/unittests/CodeGen/PassManagerTest.cpp
new file mode 100644
index 0000000..56c30f3
--- /dev/null
+++ b/backend/unittests/CodeGen/PassManagerTest.cpp
@@ -0,0 +1,260 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "Target/TestTarget.h"
+#include "rcc/CodeGen/GenericOpcodes.h"
+#include "rcc/CodeGen/MachineFunction.h"
+#include "rcc/CodeGen/MachineFunctionAnalysisManager.h"
+
+#include <atomic>
+#include <cstddef>
+#include <cstdint>
+#include <iostream>
+#include <string_view>
+#include <utility>
+#include <vector>
+
+namespace {
+
+class TestContext final {
+public:
+ void expect(bool Condition, std::string_view Message) {
+ if (Condition)
+ return;
+ std::cerr << Message << '\n';
+ ++Failures;
+ }
+
+ [[nodiscard]] int result() const noexcept {
+ return Failures == 0 ? 0 : 1;
+ }
+
+private:
+ int Failures = 0;
+};
+
+[[nodiscard]] rcc::Expected<rcc::TargetDescription> createTarget() {
+ std::vector<rcc::InstructionDescriptor> Descriptors;
+ std::vector<rcc::ImmediatePredicate> Predicates;
+ auto Appended = rcc::appendGenericInstructionInfo(Descriptors, Predicates);
+ if (!Appended)
+ return std::unexpected(Appended.error());
+ auto Instructions = rcc::InstructionSet::create(std::move(Descriptors), std::move(Predicates));
+ if (!Instructions)
+ return std::unexpected(Instructions.error());
+ return rcc::test::createTestTargetDescription(std::move(*Instructions));
+}
+
+class BlockCountAnalysis final {
+public:
+ struct Result final {
+ std::size_t Count = 0;
+ };
+
+ [[nodiscard]] static constexpr std::string_view name() noexcept {
+ return "BlockCount";
+ }
+
+ [[nodiscard]] static rcc::Expected<Result> run(rcc::MachineFunction &Function,
+ const rcc::TargetDescription &,
+ rcc::MachineFunctionAnalysisManager &) {
+ ++Runs;
+ return Result{Function.blockCount()};
+ }
+
+ static inline std::atomic<std::uint32_t> Runs = 0;
+};
+
+class DependentAnalysis final {
+public:
+ struct Result final {
+ std::size_t Count = 0;
+ };
+
+ [[nodiscard]] static constexpr std::string_view name() noexcept {
+ return "Dependent";
+ }
+
+ [[nodiscard]] static rcc::Expected<Result> run(rcc::MachineFunction &Function,
+ const rcc::TargetDescription &Target,
+ rcc::MachineFunctionAnalysisManager &Analyses) {
+ auto Blocks = Analyses.getResult<BlockCountAnalysis>(Function, Target);
+ if (!Blocks)
+ return std::unexpected(Blocks.error());
+ return Result{(*Blocks)->Count};
+ }
+};
+
+class StickyAnalysis final {
+public:
+ struct Result final {
+ [[nodiscard]] bool invalidate(const rcc::MachineFunction &,
+ const rcc::PreservedAnalyses &) noexcept {
+ return false;
+ }
+ };
+
+ [[nodiscard]] static constexpr std::string_view name() noexcept {
+ return "Sticky";
+ }
+
+ [[nodiscard]] static rcc::Expected<Result> run(rcc::MachineFunction &,
+ const rcc::TargetDescription &,
+ rcc::MachineFunctionAnalysisManager &) {
+ return Result{};
+ }
+};
+
+class ExpiringAnalysis final {
+public:
+ struct Result final {
+ [[nodiscard]] bool invalidate(const rcc::MachineFunction &,
+ const rcc::PreservedAnalyses &) noexcept {
+ return true;
+ }
+ };
+
+ [[nodiscard]] static constexpr std::string_view name() noexcept {
+ return "Expiring";
+ }
+
+ [[nodiscard]] static rcc::Expected<Result> run(rcc::MachineFunction &,
+ const rcc::TargetDescription &,
+ rcc::MachineFunctionAnalysisManager &) {
+ return Result{};
+ }
+};
+
+class CycleA final {
+public:
+ struct Result final {};
+
+ [[nodiscard]] static constexpr std::string_view name() noexcept {
+ return "CycleA";
+ }
+
+ [[nodiscard]] static rcc::Expected<Result> run(rcc::MachineFunction &,
+ const rcc::TargetDescription &,
+ rcc::MachineFunctionAnalysisManager &) {
+ return Result{};
+ }
+};
+
+class CycleB final {
+public:
+ struct Result final {};
+
+ [[nodiscard]] static constexpr std::string_view name() noexcept {
+ return "CycleB";
+ }
+
+ [[nodiscard]] static rcc::Expected<Result> run(rcc::MachineFunction &,
+ const rcc::TargetDescription &,
+ rcc::MachineFunctionAnalysisManager &) {
+ return Result{};
+ }
+};
+
+void testAnalysisManager(TestContext &Context, const rcc::TargetDescription &Target) {
+ auto Function =
+ rcc::MachineFunction::create("analysis", rcc::MachineFunctionStableID::fromValue(1));
+ Context.expect(Function.has_value(), "analysis function creation must succeed");
+ if (!Function)
+ return;
+
+ rcc::MachineFunctionAnalysisManager Analyses;
+ Context.expect(Analyses
+ .registerAnalysis<BlockCountAnalysis>({
+ .Name = "BlockCount",
+ .Dependencies = {},
+ .InvalidatedBy = {rcc::MachinePassChange::CFG},
+ })
+ .has_value(),
+ "base analysis registration must succeed");
+ Context.expect(Analyses
+ .registerAnalysis<DependentAnalysis>({
+ .Name = "Dependent",
+ .Dependencies =
+ {
+ rcc::MachineFunctionAnalysisManager::id<BlockCountAnalysis>(),
+ },
+ .InvalidatedBy = {rcc::MachinePassChange::Operands},
+ })
+ .has_value(),
+ "dependent analysis registration must succeed");
+
+ BlockCountAnalysis::Runs = 0;
+ auto First = Analyses.getResult<DependentAnalysis>(**Function, Target);
+ auto Second = Analyses.getResult<DependentAnalysis>(**Function, Target);
+ Context.expect(First && Second && *First == *Second && BlockCountAnalysis::Runs == 1,
+ "analysis dependencies must materialize once and then use the cache");
+
+ Analyses.invalidate(**Function, rcc::PreservedAnalyses::none(),
+ {rcc::MachinePassChange::Registers});
+ Context.expect(Analyses.cachedResultCount(**Function) == 2,
+ "unrelated changes must preserve cached analyses precisely");
+ Analyses.invalidate(**Function, rcc::PreservedAnalyses::none(), {rcc::MachinePassChange::CFG});
+ Context.expect(Analyses.cachedResultCount(**Function) == 0,
+ "invalidating a dependency must invalidate its dependent analysis");
+
+ rcc::MachineFunctionAnalysisManager Cyclic;
+ Context.expect(
+ Cyclic.registerAnalysis<CycleA>({
+ .Name = "CycleA",
+ .Dependencies =
+ {
+ rcc::MachineFunctionAnalysisManager::id<CycleB>(),
+ },
+ })
+ .has_value() &&
+ Cyclic
+ .registerAnalysis<CycleB>({
+ .Name = "CycleB",
+ .Dependencies =
+ {
+ rcc::MachineFunctionAnalysisManager::id<CycleA>(),
+ },
+ })
+ .has_value(),
+ "cyclic analysis registrations must be accepted until requested");
+ Context.expect(!Cyclic.getResult<CycleA>(**Function, Target),
+ "analysis dependency cycles must produce a structured error");
+
+ rcc::MachineFunctionAnalysisManager CustomInvalidation;
+ Context.expect(CustomInvalidation
+ .registerAnalysis<StickyAnalysis>({
+ .Name = "Sticky",
+ .Dependencies = {},
+ .InvalidatedBy = {rcc::MachinePassChange::CFG},
+ })
+ .has_value() &&
+ CustomInvalidation
+ .registerAnalysis<ExpiringAnalysis>({
+ .Name = "Expiring",
+ .Dependencies = {},
+ .InvalidatedBy = {rcc::MachinePassChange::CFG},
+ })
+ .has_value() &&
+ CustomInvalidation.getResult<StickyAnalysis>(**Function, Target) &&
+ CustomInvalidation.getResult<ExpiringAnalysis>(**Function, Target),
+ "custom invalidation analyses must materialize");
+ CustomInvalidation.invalidate(**Function, rcc::PreservedAnalyses::none(),
+ {rcc::MachinePassChange::CFG});
+ Context.expect(CustomInvalidation.hasCached(
+ **Function, rcc::MachineFunctionAnalysisManager::id<StickyAnalysis>()) &&
+ !CustomInvalidation.hasCached(
+ **Function, rcc::MachineFunctionAnalysisManager::id<ExpiringAnalysis>()),
+ "analysis invalidate() must return false to preserve and true to invalidate");
+}
+
+} // namespace
+
+int main() {
+ TestContext Context;
+ auto Target = createTarget();
+ Context.expect(Target.has_value(), "pass manager tests require a valid target description");
+ if (!Target)
+ return Context.result();
+
+ testAnalysisManager(Context, *Target);
+ return Context.result();
+}
diff --git a/backend/unittests/CodeGen/RegisterAllocationTest.cpp b/backend/unittests/CodeGen/RegisterAllocationTest.cpp
index 1a7c5c7..7dd0dd0 100644
--- a/backend/unittests/CodeGen/RegisterAllocationTest.cpp
+++ b/backend/unittests/CodeGen/RegisterAllocationTest.cpp
@@ -14,7 +14,7 @@
#include "rcc/CodeGen/MachineInstr.h"
#include "rcc/CodeGen/MachineMemOperand.h"
#include "rcc/CodeGen/MachineOperand.h"
-#include "rcc/CodeGen/MachinePass.h"
+#include "rcc/CodeGen/MachinePassManager.h"
#include "rcc/CodeGen/MachineRegisterInfo.h"
#include "rcc/CodeGen/RegAllocCommon.h"
#include "rcc/CodeGen/RegAllocFast.h"
@@ -496,7 +496,7 @@ enum class AllocatorKind : std::uint8_t {
const rcc::TargetRegisterAllocationInfo &Info,
AllocatorKind Kind,
rcc::RegisterAllocationOptions Options = {}) {
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
auto Registered = rcc::registerStage11MachineAnalyses(Analyses);
if (!Registered)
return std::unexpected(Registered.error());
@@ -512,7 +512,7 @@ enum class AllocatorKind : std::uint8_t {
Pass = std::make_unique<rcc::PBQPAllocatorPass>(Info, Options);
break;
}
- rcc::MachinePassManager Pipeline;
+ rcc::MachineFunctionPassManager Pipeline;
auto Added = Pipeline.addPass(std::move(Pass));
if (!Added)
return std::unexpected(Added.error());
@@ -603,7 +603,7 @@ void testLiveRegMatrix(TestContext &Context, const rcc::TargetDescription &Targe
}
if (!rcc::rebuildMachineLiveness(*LaneFixture->Function, Target))
return;
- rcc::MachineAnalysisManager LaneAnalyses;
+ rcc::MachineFunctionAnalysisManager LaneAnalyses;
if (!rcc::registerStage11MachineAnalyses(LaneAnalyses))
return;
auto LaneIntervals =
@@ -632,7 +632,7 @@ void testLiveRegMatrix(TestContext &Context, const rcc::TargetDescription &Targe
}
if (!rcc::rebuildMachineLiveness(*FixedFixture->Function, Target))
return;
- rcc::MachineAnalysisManager FixedAnalyses;
+ rcc::MachineFunctionAnalysisManager FixedAnalyses;
if (!rcc::registerStage11MachineAnalyses(FixedAnalyses))
return;
auto FixedIntervals =
@@ -664,7 +664,7 @@ void testLiveRegMatrix(TestContext &Context, const rcc::TargetDescription &Targe
!rcc::rebuildMachineLiveness(*FixedLaneFixture->Function, Target)) {
return;
}
- rcc::MachineAnalysisManager FixedLaneAnalyses;
+ rcc::MachineFunctionAnalysisManager FixedLaneAnalyses;
if (!rcc::registerStage11MachineAnalyses(FixedLaneAnalyses))
return;
auto FixedLaneIntervals =
@@ -694,7 +694,7 @@ void testSharedUnitLaneMatrix(TestContext &Context, const rcc::TargetDescription
!rcc::rebuildMachineLiveness(*Fixture->Function, Target)) {
return;
}
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
if (!rcc::registerStage11MachineAnalyses(Analyses))
return;
auto Intervals = Analyses.getResult<rcc::LiveIntervalsAnalysis>(*Fixture->Function, Target);
diff --git a/backend/unittests/CodeGen/RegisterAllocationTestSupport.h b/backend/unittests/CodeGen/RegisterAllocationTestSupport.h
index 49c9e8a..d93b14e 100644
--- a/backend/unittests/CodeGen/RegisterAllocationTestSupport.h
+++ b/backend/unittests/CodeGen/RegisterAllocationTestSupport.h
@@ -436,7 +436,7 @@ public:
const TargetRegisterAllocationInfo &Info,
AllocatorKind Kind,
RegisterAllocationOptions Options = {}) {
- MachineAnalysisManager Analyses;
+ MachineFunctionAnalysisManager Analyses;
auto Registered = registerStage11MachineAnalyses(Analyses);
if (!Registered)
return std::unexpected(Registered.error());
@@ -452,7 +452,7 @@ public:
Pass = std::make_unique<PBQPAllocatorPass>(Info, Options);
break;
}
- MachinePassManager Pipeline;
+ MachineFunctionPassManager Pipeline;
auto Added = Pipeline.addPass(std::move(Pass));
if (!Added)
return std::unexpected(Added.error());
diff --git a/backend/unittests/CodeGen/SlotIndexesTest.cpp b/backend/unittests/CodeGen/SlotIndexesTest.cpp
index d34ff84..9d3f54b 100644
--- a/backend/unittests/CodeGen/SlotIndexesTest.cpp
+++ b/backend/unittests/CodeGen/SlotIndexesTest.cpp
@@ -25,7 +25,7 @@ void testSlotIndexes(TestContext &Context, const rcc::TargetDescription &Target)
return;
}
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
auto Registered = rcc::registerStage11MachineAnalyses(Analyses);
auto Indexes =
Registered
diff --git a/backend/unittests/CodeGen/TwoAddressInstructionPassTest.cpp b/backend/unittests/CodeGen/TwoAddressInstructionPassTest.cpp
index 6853a36..e3ad4eb 100644
--- a/backend/unittests/CodeGen/TwoAddressInstructionPassTest.cpp
+++ b/backend/unittests/CodeGen/TwoAddressInstructionPassTest.cpp
@@ -3,7 +3,7 @@
#include "rcc/CodeGen/TwoAddressInstructionPass.h"
#include "SSAExitTestSupport.h"
-#include "rcc/CodeGen/MachinePass.h"
+#include "rcc/CodeGen/MachinePassManager.h"
#include "rcc/CodeGen/MachineVerifier.h"
#include <array>
@@ -130,11 +130,11 @@ void testTwoAddressAndSubregisterPseudos(TestContext &Context, const rcc::Target
if (!InitialLiveness)
return;
Function.properties().set(rcc::MachineFunctionProperty::NoPHIs);
- rcc::MachinePassManager Pipeline;
+ rcc::MachineFunctionPassManager Pipeline;
Context.expect(
Pipeline.addPass(std::make_unique<rcc::TwoAddressInstructionPass>(Info)).has_value(),
"two-address pass must be registered");
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
auto Run = Pipeline.run(Function, Target, Analyses);
Context.expect(Run.has_value(), "two-address rewrite must succeed");
if (!Run)
@@ -238,7 +238,7 @@ void testTwoAddressAndSubregisterPseudos(TestContext &Context, const rcc::Target
const std::uint64_t AtomicPropertiesBefore = AtomicFixture.Function->properties().rawValue();
TestInstrInfo RejectingInfo(true);
- rcc::MachineAnalysisManager AtomicAnalyses;
+ rcc::MachineFunctionAnalysisManager AtomicAnalyses;
rcc::TwoAddressInstructionPass FailingPass(RejectingInfo);
auto Failed = FailingPass.run(*AtomicFixture.Function, Target, AtomicAnalyses);
Context.expect(!Failed && Failed.error().code() == rcc::ErrorCode::Unsupported,
diff --git a/backend/unittests/Target/RISCVFrameLoweringTest.cpp b/backend/unittests/Target/RISCVFrameLoweringTest.cpp
index 285e962..23f1b49 100644
--- a/backend/unittests/Target/RISCVFrameLoweringTest.cpp
+++ b/backend/unittests/Target/RISCVFrameLoweringTest.cpp
@@ -12,7 +12,7 @@
#include "rcc/CodeGen/MachineInstr.h"
#include "rcc/CodeGen/MachineMemOperand.h"
#include "rcc/CodeGen/MachineOperand.h"
-#include "rcc/CodeGen/MachinePass.h"
+#include "rcc/CodeGen/MachinePassManager.h"
#include "rcc/CodeGen/PrologueEpilogueInsertion.h"
#include "rcc/CodeGen/RegisterMask.h"
#include "rcc/CodeGen/TargetDescription.h"
@@ -216,12 +216,12 @@ void setFramePassProperties(rcc::MachineFunction &Function) {
runFrameLoweringWith(rcc::MachineFunction &Function, const rcc::TargetDescription &Target,
const rcc::TargetFrameLowering &FrameLowering) {
setFramePassProperties(Function);
- rcc::MachinePassManager Pipeline;
+ rcc::MachineFunctionPassManager Pipeline;
auto Added =
Pipeline.addPass(std::make_unique<rcc::PrologueEpilogueInsertionPass>(FrameLowering));
if (!Added)
return std::unexpected(Added.error());
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
return Pipeline.run(Function, Target, Analyses);
}
diff --git a/backend/unittests/Target/RISCVLateCodeGenTest.cpp b/backend/unittests/Target/RISCVLateCodeGenTest.cpp
index 702f058..868d18f 100644
--- a/backend/unittests/Target/RISCVLateCodeGenTest.cpp
+++ b/backend/unittests/Target/RISCVLateCodeGenTest.cpp
@@ -18,7 +18,7 @@
#include "rcc/CodeGen/MachineMemoryFolding.h"
#include "rcc/CodeGen/MachineOperand.h"
#include "rcc/CodeGen/MachineOptimizationPipeline.h"
-#include "rcc/CodeGen/MachinePass.h"
+#include "rcc/CodeGen/MachinePassManager.h"
#include "rcc/CodeGen/MachinePseudoExpansion.h"
#include "rcc/CodeGen/MachineShrinkWrapping.h"
#include "rcc/CodeGen/MachineStackSlotColoring.h"
@@ -376,7 +376,7 @@ void testBlockPlacement(TestContext &Context, const rcc::TargetDescription &Targ
CFG.addSuccessor(*Entry, *Hot, *HotProbability).has_value(),
"placement CFG construction must succeed");
setSelectedProperties(*Function);
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
rcc::MachineBlockPlacementPass Pass;
auto Result = Pass.run(*Function, Target, Analyses);
if (!Result)
@@ -410,7 +410,7 @@ void testFallthroughNormalization(TestContext &Context, const rcc::TargetDescrip
setPostRAProperties(*Function);
auto Liveness = rcc::rebuildMachineLiveness(*Function, Target);
Context.expect(Liveness.has_value(), "fallthrough fixture liveness must be rebuilt");
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
rcc::MachineFallthroughPass Pass(rcc::riscv::instrInfo());
auto Result = Pass.run(*Function, Target, Analyses);
if (!Result)
@@ -445,7 +445,7 @@ void testFallthroughMaterialization(TestContext &Context, const rcc::TargetDescr
setPostRAProperties(*Function);
Context.expect(rcc::rebuildMachineLiveness(*Function, Target).has_value(),
"materialized fallthrough liveness must be rebuilt");
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
rcc::MachineFallthroughPass Pass(rcc::riscv::instrInfo());
auto Result = Pass.run(*Function, Target, Analyses);
if (!Result)
@@ -486,7 +486,7 @@ void testBranchOptimization(TestContext &Context, const rcc::TargetDescription &
return;
}
setSelectedProperties(*Function);
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
rcc::MachineBranchOptimizationPass Pass(rcc::riscv::instrInfo());
auto Result = Pass.run(*Function, Target, Analyses);
if (!Result)
@@ -522,7 +522,7 @@ void testBranchOptimization(TestContext &Context, const rcc::TargetDescription &
return;
}
setSelectedProperties(*ConstantFunction);
- rcc::MachineAnalysisManager ConstantAnalyses;
+ rcc::MachineFunctionAnalysisManager ConstantAnalyses;
auto ConstantResult = Pass.run(*ConstantFunction, Target, ConstantAnalyses);
if (!ConstantResult)
std::cerr << "constant branch folding failure: " << ConstantResult.error().message() << '\n';
@@ -566,7 +566,7 @@ void testTailDuplication(TestContext &Context, const rcc::TargetDescription &Tar
return;
}
setRelaxationProperties(Context, *Function, Target);
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
rcc::MachineTailDuplicationPass Pass(rcc::riscv::instrInfo());
Tail->attributes().set(rcc::MachineBasicBlockAttribute::MachineBlockAddressTaken);
auto Protected = Pass.run(*Function, Target, Analyses);
@@ -617,7 +617,7 @@ void testTailMerge(TestContext &Context, const rcc::TargetDescription &Target) {
return;
}
setRelaxationProperties(Context, *Function, Target);
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
rcc::MachineTailMergePass Pass(rcc::riscv::instrInfo());
Second->attributes().set(rcc::MachineBasicBlockAttribute::MachineBlockAddressTaken);
auto Protected = Pass.run(*Function, Target, Analyses);
@@ -662,7 +662,7 @@ void testCopyPropagation(TestContext &Context, const rcc::TargetDescription &Tar
if (Add == nullptr)
return;
setSelectedProperties(*Function);
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
rcc::MachineCopyPropagationPass PreRA(rcc::riscv::instrInfo(),
rcc::MachineCopyPropagationStage::PreRegisterAllocation);
auto PreResult = PreRA.run(*Function, Target, Analyses);
@@ -702,7 +702,7 @@ void testCopyPropagation(TestContext &Context, const rcc::TargetDescription &Tar
setPostRAProperties(*PostFunction);
Context.expect(rcc::rebuildMachineLiveness(*PostFunction, Target).has_value(),
"post-RA COPY propagation liveness must be rebuilt");
- rcc::MachineAnalysisManager PostAnalyses;
+ rcc::MachineFunctionAnalysisManager PostAnalyses;
rcc::MachineCopyPropagationPass PostRA(rcc::riscv::instrInfo(),
rcc::MachineCopyPropagationStage::PostRegisterAllocation);
auto PostResult = PostRA.run(*PostFunction, Target, PostAnalyses);
@@ -752,7 +752,7 @@ void testStackSlotColoring(TestContext &Context, const rcc::TargetDescription &T
setPostRAProperties(*Function);
Context.expect(rcc::rebuildMachineLiveness(*Function, Target).has_value(),
"stack-slot coloring liveness must be rebuilt");
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
rcc::MachineStackSlotColoringPass Pass;
auto Result = Pass.run(*Function, Target, Analyses);
if (!Result)
@@ -836,7 +836,7 @@ void testRISCVMemoryFoldingBoundary(TestContext &Context, const rcc::TargetDescr
return;
setSelectedProperties(*Function);
Function->properties().set(rcc::MachineFunctionProperty::IsSSA);
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
rcc::MachineMemoryFoldingPass Pass(rcc::riscv::memoryFoldingInfo());
auto Result = Pass.run(*Function, Target, Analyses);
if (!Result)
@@ -894,7 +894,7 @@ void testShrinkWrappedFrameRegion(TestContext &Context, const rcc::TargetDescrip
setPostRAProperties(*Function);
Context.expect(rcc::rebuildMachineLiveness(*Function, Target).has_value(),
"shrink-wrapping fixture liveness must be rebuilt");
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
rcc::MachineShrinkWrappingPass Shrink{rcc::riscv::frameLowering()};
auto Shrunk = Shrink.run(*Function, Target, Analyses);
Context.expect(Shrunk && Shrunk->Changed &&
@@ -906,7 +906,7 @@ void testShrinkWrappedFrameRegion(TestContext &Context, const rcc::TargetDescrip
if (!Shrunk)
return;
- rcc::MachinePassManager FramePipeline;
+ rcc::MachineFunctionPassManager FramePipeline;
Context.expect(FramePipeline
.addPass(std::make_unique<rcc::PrologueEpilogueInsertionPass>(
rcc::riscv::frameLowering()))
@@ -975,7 +975,7 @@ void testCompressedAndConditionalRelaxation(TestContext &Context,
if (Conditional == nullptr)
return;
setRelaxationProperties(Context, *Function, Target);
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
rcc::MachineBranchRelaxationPass Pass(rcc::riscv::instrInfo());
auto Result = Pass.run(*Function, Target, Analyses);
if (!Result)
@@ -1108,7 +1108,7 @@ void testPseudoPreparation(TestContext &Context, const rcc::TargetDescription &T
if (!Copy)
return;
setSelectedProperties(*Function);
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
rcc::PreparePostRAPseudosPass Pass(rcc::riscv::pseudoExpansionInfo());
auto Result = Pass.run(*Function, Target, Analyses);
Context.expect(Result && Result->Changed && (*Copy)->operandAt(0)->targetFlags() == 16 &&
@@ -1170,7 +1170,7 @@ void testPostRAPseudoExpansionAndFinalization(TestContext &Context,
setRelaxationProperties(Context, *Function, Target);
Function->properties().clear(rcc::MachineFunctionProperty::NoExecutablePseudos);
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
rcc::ExpandPostRAPseudosPass Expansion(rcc::riscv::pseudoExpansionInfo());
auto Expanded = Expansion.run(*Function, Target, Analyses);
if (!Expanded)
@@ -1196,7 +1196,7 @@ void testPostRAPseudoExpansionAndFinalization(TestContext &Context,
if (!Expanded)
return;
- rcc::MachinePassManager Pipeline;
+ rcc::MachineFunctionPassManager Pipeline;
Context.expect(Pipeline.addPass(std::make_unique<rcc::FinalizeEmissionPseudosPass>()) &&
Pipeline.addPass(std::make_unique<rcc::FinalEncodabilityVerifierPass>(
rcc::riscv::instrInfo())),
@@ -1213,8 +1213,8 @@ void testCanonicalOptimizationPipelines(TestContext &Context,
const rcc::TargetDescription &Target) {
const rcc::MachineOptimizationPipelineTargetInfo TargetInfo =
rcc::riscv::optimizationPipelineInfo();
- rcc::MachinePassManager SelectedPipeline;
- rcc::MachinePassManager PreRAPipeline;
+ rcc::MachineFunctionPassManager SelectedPipeline;
+ rcc::MachineFunctionPassManager PreRAPipeline;
Context.expect(rcc::addSelectedSSAOptimizationPipeline(SelectedPipeline, TargetInfo) &&
SelectedPipeline.size() == 6,
"canonical selected-SSA optimization pipeline must register completely");
@@ -1259,13 +1259,13 @@ void testCanonicalOptimizationPipelines(TestContext &Context,
return;
}
- rcc::MachinePassManager Pipeline;
+ rcc::MachineFunctionPassManager Pipeline;
auto Added = rcc::addPostRegisterAllocationPipeline(Pipeline, TargetInfo);
Context.expect(Added && Pipeline.size() == 20,
"canonical post-RA pipeline must register every required pass");
if (!Added)
return;
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
auto Registered = rcc::registerMachineOptimizationAnalyses(Analyses);
Context.expect(Registered.has_value(),
"canonical optimization analyses must register completely");
@@ -1325,7 +1325,7 @@ void testTargetLateExpansionRejectsSizeGrowth(TestContext &Context) {
GrowingLatePseudoInfo ExpansionInfo;
FixedSizeInstrInfo InstrInfo;
rcc::TargetLatePseudoExpansionPass Pass(ExpansionInfo, InstrInfo);
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
auto Result = Pass.run(*Function, *Target, Analyses);
Context.expect(!Result && Result.error().code() == rcc::ErrorCode::PseudoExpansionFailed &&
(*Pseudo)->parent() == Block && Block->firstInstruction() == *Pseudo &&
@@ -1373,7 +1373,7 @@ void testTargetLateExpansionRejectsCompensatedGrowth(TestContext &Context) {
GrowingLatePseudoInfo ExpansionInfo;
FixedSizeInstrInfo InstrInfo;
rcc::TargetLatePseudoExpansionPass Pass(ExpansionInfo, InstrInfo);
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
auto Result = Pass.run(*Function, *Target, Analyses);
Context.expect(
!Result && Result.error().code() == rcc::ErrorCode::PseudoExpansionFailed &&
@@ -1403,7 +1403,7 @@ void testFinalEncodabilityRejectsInvalidInstruction(TestContext &Context,
return;
}
setRelaxationProperties(Context, *ImmediateFunction, Target);
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
rcc::FinalEncodabilityVerifierPass Verifier(rcc::riscv::instrInfo());
auto ImmediateResult = Verifier.run(*ImmediateFunction, Target, Analyses);
Context.expect(!ImmediateResult &&
diff --git a/backend/unittests/Target/RISCVRegisterAllocationTest.cpp b/backend/unittests/Target/RISCVRegisterAllocationTest.cpp
index 0e60e63..acd4b3a 100644
--- a/backend/unittests/Target/RISCVRegisterAllocationTest.cpp
+++ b/backend/unittests/Target/RISCVRegisterAllocationTest.cpp
@@ -11,7 +11,7 @@
#include "rcc/CodeGen/MachineInstr.h"
#include "rcc/CodeGen/MachineMemOperand.h"
#include "rcc/CodeGen/MachineOperand.h"
-#include "rcc/CodeGen/MachinePass.h"
+#include "rcc/CodeGen/MachinePassManager.h"
#include "rcc/CodeGen/MachineRegisterInfo.h"
#include "rcc/CodeGen/RegAllocCommon.h"
#include "rcc/CodeGen/RegAllocFast.h"
@@ -168,7 +168,7 @@ enum class AllocatorKind : std::uint8_t {
const rcc::TargetDescription &Target,
AllocatorKind Kind,
rcc::RegisterAllocationOptions Options = {}) {
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
auto Registered = rcc::registerStage11MachineAnalyses(Analyses);
if (!Registered)
return std::unexpected(Registered.error());
@@ -184,7 +184,7 @@ enum class AllocatorKind : std::uint8_t {
Pass = std::make_unique<rcc::PBQPAllocatorPass>(rcc::riscv::registerAllocationInfo(), Options);
break;
}
- rcc::MachinePassManager Pipeline;
+ rcc::MachineFunctionPassManager Pipeline;
auto Added = Pipeline.addPass(std::move(Pass));
if (!Added)
return std::unexpected(Added.error());
diff --git a/backend/unittests/Target/RISCVSSAExitTest.cpp b/backend/unittests/Target/RISCVSSAExitTest.cpp
index ab30572..ec98bd1 100644
--- a/backend/unittests/Target/RISCVSSAExitTest.cpp
+++ b/backend/unittests/Target/RISCVSSAExitTest.cpp
@@ -10,7 +10,7 @@
#include "rcc/CodeGen/MachineIRBuilder.h"
#include "rcc/CodeGen/MachineInstr.h"
#include "rcc/CodeGen/MachineOperand.h"
-#include "rcc/CodeGen/MachinePass.h"
+#include "rcc/CodeGen/MachinePassManager.h"
#include "rcc/CodeGen/MachineVerifier.h"
#include "rcc/CodeGen/PHIElimination.h"
#include "rcc/Target/RISCV/RISCVTarget.h"
@@ -352,12 +352,12 @@ void testRV64GCCriticalEdge(TestContext &Context, const rcc::TargetDescription &
if (!InitialLiveness)
return;
- rcc::MachinePassManager Pipeline;
+ rcc::MachineFunctionPassManager Pipeline;
Context.expect(
Pipeline.addPass(std::make_unique<rcc::PHIEliminationPass>(rcc::riscv::instrInfo()))
.has_value(),
"RV64GC PHI-elimination pass must be registered");
- rcc::MachineAnalysisManager Analyses;
+ rcc::MachineFunctionAnalysisManager Analyses;
auto Run = Pipeline.run(**Function, Target, Analyses);
Context.expect(Run.has_value(), "RV64GC critical-edge PHI elimination must succeed");
if (!Run)