aboutsummaryrefslogtreecommitdiff
path: root/backend/lib/CodeGen/MachinePeepholeOptimizer.cpp
diff options
context:
space:
mode:
authorRichard-Qin-X <richard.qin.001@gmail.com>2026-08-24 16:18:45 +0800
committerRichard-Qin-X <richard.qin.001@gmail.com>2026-08-24 16:18:45 +0800
commit936ac5647f82def050e6654d44d24a88906f4d7a (patch)
tree7ab0c695b51eb1c449c4390d18ca3d682ecd31ba /backend/lib/CodeGen/MachinePeepholeOptimizer.cpp
parent75f1223070749b0df3002226ebbb474c68c71f90 (diff)
downloadrcc-project-936ac5647f82def050e6654d44d24a88906f4d7a.tar.gz
rcc-project-936ac5647f82def050e6654d44d24a88906f4d7a.tar.xz
[CodeGen] Implement RISC-V peephole branch optimization
Diffstat (limited to 'backend/lib/CodeGen/MachinePeepholeOptimizer.cpp')
-rw-r--r--backend/lib/CodeGen/MachinePeepholeOptimizer.cpp94
1 files changed, 94 insertions, 0 deletions
diff --git a/backend/lib/CodeGen/MachinePeepholeOptimizer.cpp b/backend/lib/CodeGen/MachinePeepholeOptimizer.cpp
new file mode 100644
index 0000000..f874699
--- /dev/null
+++ b/backend/lib/CodeGen/MachinePeepholeOptimizer.cpp
@@ -0,0 +1,94 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "rcc/CodeGen/MachinePeepholeOptimizer.h"
+
+#include "rcc/CodeGen/MachineBasicBlock.h"
+#include "rcc/CodeGen/MachineFunction.h"
+#include "rcc/CodeGen/MachineFunctionCloner.h"
+#include "rcc/CodeGen/MachineInstr.h"
+#include "rcc/CodeGen/TargetDescription.h"
+#include "rcc/CodeGen/TargetInstrInfo.h"
+
+#include <optional>
+
+namespace rcc {
+namespace {
+
+[[nodiscard]] const MachinePassContract &peepholeOptimizerContract() {
+ static const MachinePassContract Contract = [] {
+ MachinePassContract Value{
+ .Name = "peephole-opt",
+ .Requires = {MachineFunctionProperty::IsSSA},
+ .Sets = {},
+ .Clears = {},
+ .RequiredAnalyses = {},
+ .VerificationStage = PipelineStage::Selected,
+ };
+ Value.ThreadSafety = PassThreadSafety::ThreadSafe;
+ Value.DeclaredChanges = {MachinePassChange::Instructions, MachinePassChange::Operands,
+ MachinePassChange::Registers};
+ return Value;
+ }();
+ return Contract;
+}
+
+} // namespace
+
+const MachinePassContract &MachinePeepholeOptimizerPass::contract() const noexcept {
+ return peepholeOptimizerContract();
+}
+
+Expected<MachinePassResult> MachinePeepholeOptimizerPass::run(MachineFunction &Function,
+ const TargetDescription &Target,
+ MachineFunctionAnalysisManager &) {
+ if (!Function.properties().containsAll(contract().Requires)) {
+ return makeUnexpected(ErrorCode::VerificationError,
+ "machine peephole optimizer requires SSA MachineIR");
+ }
+
+ auto Trial = cloneMachineFunction(
+ Function, Target,
+ MachineFunctionCloneOptions{.NewStableID = Function.stableID(), .NewName = std::nullopt});
+ if (!Trial) {
+ return std::unexpected(
+ withErrorContext(Trial.error(), "machine peephole transaction setup failed: "));
+ }
+ auto TrialResult = runImplementation(*Trial->ClonedFunction, Target);
+ if (!TrialResult)
+ return std::unexpected(TrialResult.error());
+
+ auto Result = runImplementation(Function, Target);
+ if (!Result) {
+ return std::unexpected(withErrorContext(
+ Result.error(), "machine peephole diverged after a successful transaction preflight: "));
+ }
+ return Result;
+}
+
+Expected<MachinePassResult>
+MachinePeepholeOptimizerPass::runImplementation(MachineFunction &Function,
+ const TargetDescription &Target) const {
+ MachinePassResult Result;
+ for (MachineBasicBlock *Block = Function.firstBlock(); Block != nullptr; Block = Block->next()) {
+ for (MachineInstr *Instruction = Block->firstInstruction(); Instruction != nullptr;) {
+ MachineInstr *Next = Instruction->next();
+ if (!Instruction->isDebugInstr()) {
+ auto Changed = Info->optimizeCondBranch(*Instruction, Function, Target);
+ if (!Changed)
+ return std::unexpected(Changed.error());
+ Result.Changed |= *Changed;
+ }
+ Instruction = Next;
+ }
+ }
+ if (Result.Changed) {
+ Result.Changes = {MachinePassChange::Instructions, MachinePassChange::Operands,
+ MachinePassChange::Registers};
+ Result.Preserved = PreservedAnalyses::none();
+ } else {
+ Result.Preserved = PreservedAnalyses::all();
+ }
+ return Result;
+}
+
+} // namespace rcc