aboutsummaryrefslogtreecommitdiff
path: root/backend/lib/Target/RISCV/RISCVScheduling.cpp
diff options
context:
space:
mode:
authorRichard-Qin-X <richard.qin.001@gmail.com>2026-08-09 17:03:19 +0800
committerRichard-Qin-X <richard.qin.001@gmail.com>2026-08-09 17:03:19 +0800
commit495c675771f43cfa12ab7a426a538be72fec1805 (patch)
tree4107223d6c6ef2e74d56064aa21b196307502342 /backend/lib/Target/RISCV/RISCVScheduling.cpp
parentda8bc76b4bf7d1a7b025d6c8ef5809551467dcc7 (diff)
downloadrcc-project-495c675771f43cfa12ab7a426a538be72fec1805.tar.gz
rcc-project-495c675771f43cfa12ab7a426a538be72fec1805.tar.xz
[CodeGen] Implement machine optimization and scheduling
Diffstat (limited to 'backend/lib/Target/RISCV/RISCVScheduling.cpp')
-rw-r--r--backend/lib/Target/RISCV/RISCVScheduling.cpp136
1 files changed, 136 insertions, 0 deletions
diff --git a/backend/lib/Target/RISCV/RISCVScheduling.cpp b/backend/lib/Target/RISCV/RISCVScheduling.cpp
new file mode 100644
index 0000000..8ef8d91
--- /dev/null
+++ b/backend/lib/Target/RISCV/RISCVScheduling.cpp
@@ -0,0 +1,136 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "rcc/Target/RISCV/RISCVCodeGen.h"
+#include "rcc/Target/RISCV/RISCVTarget.h"
+
+#include <cstdint>
+#include <cstdlib>
+#include <optional>
+#include <string>
+#include <utility>
+#include <vector>
+
+namespace rcc::riscv {
+namespace {
+
+enum class Resource : std::uint32_t {
+ Core = 1,
+ IntegerALU = 2,
+ Memory = 3,
+ Branch = 4,
+ MultiplyDivide = 5,
+ FloatingPoint = 6,
+ System = 7,
+};
+
+enum class PressureSet : std::uint32_t {
+ GPR = 1,
+ FPR = 2,
+};
+
+[[nodiscard]] constexpr ProcessorResourceID resource(Resource Value) noexcept {
+ return ProcessorResourceID::fromValue(static_cast<std::uint32_t>(Value));
+}
+
+[[nodiscard]] constexpr RegisterPressureSetID pressureSet(PressureSet Value) noexcept {
+ return RegisterPressureSetID::fromValue(static_cast<std::uint32_t>(Value));
+}
+
+[[nodiscard]] constexpr RegisterClassID registerClass(RegisterClass Value) noexcept {
+ return RegisterClassID::fromValue(static_cast<std::uint32_t>(Value));
+}
+
+[[nodiscard]] std::vector<SchedulingResourceUse> resourceUses(SchedulingClass Class) {
+ switch (Class) {
+ case SchedulingClass::ALU:
+ case SchedulingClass::COMPRESSED:
+ return {{resource(Resource::IntegerALU), 1}};
+ case SchedulingClass::LOAD:
+ case SchedulingClass::STORE:
+ return {{resource(Resource::Memory), 1}};
+ case SchedulingClass::BRANCH:
+ return {{resource(Resource::Branch), 1}};
+ case SchedulingClass::SYSTEM:
+ case SchedulingClass::FENCE:
+ return {{resource(Resource::System), 1}};
+ case SchedulingClass::MUL:
+ return {{resource(Resource::MultiplyDivide), 3}};
+ case SchedulingClass::DIV:
+ return {{resource(Resource::MultiplyDivide), 20}};
+ case SchedulingClass::ATOMIC:
+ return {{resource(Resource::Memory), 4}, {resource(Resource::System), 1}};
+ case SchedulingClass::FP_ADD:
+ case SchedulingClass::FP_MUL:
+ case SchedulingClass::FP_CONVERT:
+ return {{resource(Resource::FloatingPoint), 4}};
+ case SchedulingClass::FP_DIV:
+ case SchedulingClass::FP_SQRT:
+ return {{resource(Resource::FloatingPoint), 20}};
+ case SchedulingClass::None:
+ return {};
+ }
+ return {};
+}
+
+[[nodiscard]] TargetSchedulingModelDesc createDescription() {
+ TargetSchedulingModelDesc Description;
+ Description.IssueWidth = 2;
+ Description.DispatchLimit = 2;
+ Description.ProcessorResources = {
+ {resource(Resource::Core), "core", 2, std::nullopt},
+ {resource(Resource::IntegerALU), "integer-alu", 2, resource(Resource::Core)},
+ {resource(Resource::Memory), "memory", 1, resource(Resource::Core)},
+ {resource(Resource::Branch), "branch", 1, resource(Resource::Core)},
+ {resource(Resource::MultiplyDivide), "multiply-divide", 1, resource(Resource::Core)},
+ {resource(Resource::FloatingPoint), "floating-point", 1, resource(Resource::Core)},
+ {resource(Resource::System), "system", 1, resource(Resource::Core)},
+ };
+ for (const SchedulingClassInfo &Class : schedulingClasses()) {
+ SchedulingClassModelDesc Model{
+ .ID = Class.ID,
+ .Name = std::string(Class.Name),
+ .MicroOps = Class.MicroOps,
+ .Latency = Class.Latency,
+ .Resources = resourceUses(static_cast<SchedulingClass>(Class.ID.value())),
+ .WriteLatencies = {},
+ .ReadAdvances = {},
+ };
+ Model.WriteLatencies.push_back({0, Class.Latency});
+ switch (static_cast<SchedulingClass>(Class.ID.value())) {
+ case SchedulingClass::ALU:
+ Model.ReadAdvances = {
+ {1, SchedulingClassID::fromValue(static_cast<std::uint32_t>(SchedulingClass::LOAD)), 1},
+ {2, SchedulingClassID::fromValue(static_cast<std::uint32_t>(SchedulingClass::LOAD)), 1},
+ };
+ break;
+ default:
+ break;
+ }
+ Description.SchedulingClasses.push_back(std::move(Model));
+ }
+ Description.PressureSets = {
+ {pressureSet(PressureSet::GPR),
+ "gpr",
+ {registerClass(RegisterClass::GPR), registerClass(RegisterClass::GPRC),
+ registerClass(RegisterClass::GPR_NX0), registerClass(RegisterClass::GPR_NX0_NX2)},
+ 27},
+ {pressureSet(PressureSet::FPR),
+ "fpr",
+ {registerClass(RegisterClass::FPR64), registerClass(RegisterClass::FPR64C),
+ registerClass(RegisterClass::FPR32), registerClass(RegisterClass::FPR32C)},
+ 32},
+ };
+ return Description;
+}
+
+} // namespace
+
+const TargetSchedulingModel &schedulingModel() noexcept {
+ static const Expected<TargetSchedulingModel> Model =
+ TargetSchedulingModel::create(createDescription());
+ if (!Model)
+ std::abort();
+ return *Model;
+}
+
+} // namespace rcc::riscv