16#include "mlir/IR/PatternMatch.h"
17#include "llvm/Support/Debug.h"
21#define GEN_PASS_DEF_LINEARSCANREGISTERALLOCATIONPASS
22#include "circt/Dialect/RTG/Transforms/RTGPasses.h.inc"
29#define DEBUG_TYPE "rtg-linear-scan-register-allocation"
34struct RegisterLiveRange {
35 rtg::RegisterAttrInterface fixedReg;
36 rtg::VirtualRegisterOp regOp;
41class LinearScanRegisterAllocationPass
42 :
public circt::rtg::impl::LinearScanRegisterAllocationPassBase<
43 LinearScanRegisterAllocationPass> {
45 void runOnOperation()
override;
51 RegisterLiveRange *reg) {
53 llvm::sort(active, [](
auto *a,
auto *b) {
return a->end < b->end; });
55 for (
auto *iter = active.begin(); iter != active.end(); ++iter) {
57 if (a->end >= reg->start)
64void LinearScanRegisterAllocationPass::runOnOperation() {
65 auto testOp = getOperation();
67 LLVM_DEBUG(llvm::dbgs() <<
"=== Processing test @" << testOp.getSymName()
70 DenseMap<Operation *, unsigned> opIndices;
72 for (
auto [i, op] :
llvm::enumerate(*testOp.getBody())) {
79 SmallVector<std::unique_ptr<RegisterLiveRange>> regRanges;
80 SmallVector<RegisterLiveRange *> active;
81 for (
auto &op : *testOp.getBody()) {
82 if (!isa<rtg::FixedRegisterOp, rtg::VirtualRegisterOp>(&op))
89 if (
auto regOp = dyn_cast<rtg::VirtualRegisterOp>(&op))
92 if (
auto regOp = dyn_cast<rtg::FixedRegisterOp>(&op))
93 lr.fixedReg = regOp.getReg();
95 for (
auto *user : op.getUsers()) {
96 if (!isa<rtg::InstructionOpInterface>(user)) {
97 user->emitError(
"only operations implementing 'InstructionOpInterface "
98 "are allowed to use registers");
99 return signalPassFailure();
103 unsigned idx = opIndices.at(user);
104 lr.start = std::min(lr.start, idx);
105 lr.end = std::max(lr.end, idx);
108 regRanges.emplace_back(std::make_unique<RegisterLiveRange>(lr));
116 active.push_back(regRanges.back().get());
120 llvm::sort(regRanges, [](
const auto &a,
const auto &b) {
121 return a->start < b->start || (a->start == b->start && !a->regOp);
124 for (
auto &lr : regRanges) {
133 rtg::RegisterAttrInterface availableReg;
134 for (
auto reg : lr->regOp.getAllowedRegs()) {
135 if (llvm::none_of(active, [&](
auto *r) {
return r->fixedReg ==
reg; })) {
136 availableReg = cast<rtg::RegisterAttrInterface>(reg);
142 ++numRegistersSpilled;
143 lr->regOp->emitError(
144 "need to spill this register, but not supported yet");
145 return signalPassFailure();
148 lr->fixedReg = availableReg;
149 active.push_back(lr.get());
153 for (
auto ®Range : regRanges) {
154 llvm::dbgs() <<
"Start: " << regRange->start <<
", End: " << regRange->end
155 <<
", Selected: " << regRange->fixedReg <<
"\n";
157 llvm::dbgs() <<
"\n";
160 for (
auto ® : regRanges) {
165 IRRewriter rewriter(
reg->regOp);
166 rewriter.replaceOpWithNewOp<rtg::FixedRegisterOp>(
reg->regOp,
static void expireOldInterval(SmallVector< RegisterLiveRange * > &active, RegisterLiveRange *reg)
The InstanceGraph op interface, see InstanceGraphInterface.td for more details.
reg(value, clock, reset=None, reset_value=None, name=None, sym_name=None)