aboutsummaryrefslogtreecommitdiff
path: root/backend/lib/Tooling/PipelineDriver.cpp
diff options
context:
space:
mode:
authorRichard-Qin-X <richard.qin.001@gmail.com>2026-08-25 02:21:25 +0800
committerRichard-Qin-X <richard.qin.001@gmail.com>2026-08-25 02:21:25 +0800
commit71988f9818677df0d90b19d4bb770ac8a6116e62 (patch)
treeabc6a548dc50fefd1e2882fd33fe652776c0bb6a /backend/lib/Tooling/PipelineDriver.cpp
parent6dc798fbdbef20670317742a8c1d12f47e9d1c05 (diff)
downloadrcc-project-71988f9818677df0d90b19d4bb770ac8a6116e62.tar.gz
rcc-project-71988f9818677df0d90b19d4bb770ac8a6116e62.tar.xz
[CodeGen] Implement RISC-V machine outlining
Diffstat (limited to 'backend/lib/Tooling/PipelineDriver.cpp')
-rw-r--r--backend/lib/Tooling/PipelineDriver.cpp67
1 files changed, 64 insertions, 3 deletions
diff --git a/backend/lib/Tooling/PipelineDriver.cpp b/backend/lib/Tooling/PipelineDriver.cpp
index ebba1b6..b247326 100644
--- a/backend/lib/Tooling/PipelineDriver.cpp
+++ b/backend/lib/Tooling/PipelineDriver.cpp
@@ -6,6 +6,7 @@
#include "rcc/CodeGen/MIRPrinter.h"
#include "rcc/CodeGen/MachineFunction.h"
#include "rcc/CodeGen/MachineOptimizationPipeline.h"
+#include "rcc/CodeGen/MachineOutliner.h"
#include "rcc/CodeGen/MachineStripDebug.h"
#include "rcc/CodeGen/MachineVerifier.h"
#include "rcc/Target/RISCV/RISCVPipeline.h"
@@ -98,6 +99,12 @@ struct FunctionRunResult final {
return false;
}
+[[nodiscard]] bool booleanTargetOption(const BackendInvocation &Invocation,
+ std::string_view Name) noexcept {
+ const auto Option = std::ranges::find(Invocation.TargetOptions, Name, &BackendOption::Name);
+ return Option != Invocation.TargetOptions.end() && Option->Value == "true";
+}
+
[[nodiscard]] std::optional<BackendStage> stageAfterPass(std::string_view Pass) noexcept {
if (Pass == "legalizer")
return BackendStage::LegalizedMIR;
@@ -175,9 +182,11 @@ createPasses(const MachineFunction &Function, const BackendInvocation &Invocatio
Comma == std::string_view::npos ? Selector : Selector.substr(0, Comma);
if (Name.empty())
return makeUnexpected(ErrorCode::InvalidInvocation, "empty pipeline pass selector");
- auto Pass = riscv::createCanonicalPipelinePass(Name, Subtarget);
- if (!Pass)
- return std::unexpected(Pass.error());
+ if (Name != "machine-outliner") {
+ auto Pass = riscv::createCanonicalPipelinePass(Name, Subtarget);
+ if (!Pass)
+ return std::unexpected(Pass.error());
+ }
if (Comma != std::string_view::npos) {
const std::string_view InstanceText = Selector.substr(Comma + 1U);
std::uint32_t Instance = 0;
@@ -383,6 +392,47 @@ runFunction(MachineFunction &Function, mir::MIRDocument &Document, const TargetD
!Controls.PrintAfter.empty();
}
+[[nodiscard]] Expected<PipelineRunResult>
+runMachineOutliner(mir::MIRDocument &Document, const TargetDescription &Target,
+ const BackendInvocation &Invocation, const PipelineControls &Controls,
+ MachinePassInstrumentation *Instrumentation) {
+ auto TargetInfo =
+ riscv::createMachineOutlinerInfo(booleanTargetOption(Invocation, "function-sections"),
+ booleanTargetOption(Invocation, "riscv-outliner-regsave"));
+ if (!TargetInfo)
+ return std::unexpected(TargetInfo.error());
+
+ MachineOutlinerOptions Options;
+ if (const mir::EmbeddedIRReferenceIndex *Embedded = Document.embeddedIR()) {
+ for (const mir::EmbeddedIRFunction &IRFunction : Embedded->functions()) {
+ Options.FunctionProperties.emplace(std::string(IRFunction.name()),
+ MachineOutlinerFunctionProperties{
+ .LinkOnceODR = IRFunction.hasLinkOnceODRLinkage(),
+ .HasSection = IRFunction.hasSection(),
+ .HasComdat = IRFunction.hasComdat(),
+ .HasSectionPrefix = IRFunction.hasSectionPrefix(),
+ });
+ }
+ }
+
+ CompilationUnitPassManager Pipeline({.VerifyBefore = true, .VerifyEach = Controls.VerifyEach});
+ auto Added =
+ Pipeline.addPass(createMachineOutlinerPass(std::move(*TargetInfo), std::move(Options)));
+ if (!Added)
+ return std::unexpected(Added.error());
+ CompilationUnitAnalysisManager UnitAnalyses;
+ MachineFunctionAnalysisManager FunctionAnalyses;
+ auto Registered = registerMachineOptimizationAnalyses(FunctionAnalyses);
+ if (!Registered)
+ return std::unexpected(Registered.error());
+ auto Run = Pipeline.run(Document.unit(), Target, UnitAnalyses, FunctionAnalyses, Instrumentation);
+ if (!Run)
+ return std::unexpected(Run.error());
+ PipelineRunResult Result;
+ Result.ExecutedPasses.push_back({.Function = {}, .Pass = "machine-outliner", .Occurrence = 1});
+ return Result;
+}
+
} // namespace
bool isEarlierStage(BackendStage Left, BackendStage Right) noexcept {
@@ -516,6 +566,17 @@ Expected<PipelineRunResult> runRV64GCPipeline(mir::MIRDocument &Document,
});
}
+ const bool ContainsMachineOutliner =
+ std::ranges::find(Invocation.PassPipeline, "machine-outliner") !=
+ Invocation.PassPipeline.end();
+ if (ContainsMachineOutliner) {
+ if (Invocation.PassPipeline.size() != 1) {
+ return makeUnexpected(ErrorCode::InvalidInvocation,
+ "machine-outliner cannot be mixed with per-function passes");
+ }
+ return runMachineOutliner(Document, Target, Invocation, Controls, ActiveInstrumentation);
+ }
+
const std::size_t FunctionCount = Document.unit().functionCount();
std::vector<FunctionRunResult> FunctionResults(FunctionCount);
const bool Sequential = requiresSequentialExecution(Controls) ||