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 LLVM_DEBUG(llvm::dbgs() <<
"=== Processing "
66 << OpWithFlags(getOperation(),
67 OpPrintingFlags().skipRegions())
70 if (getOperation()->getNumRegions() != 1 ||
71 getOperation()->getRegion(0).getBlocks().size() != 1) {
72 getOperation()->emitError(
"expected a single region with a single block");
73 return signalPassFailure();
76 DenseMap<Operation *, unsigned> opIndices;
79 llvm::enumerate(getOperation()->getRegion(0).getBlocks().front())) {
86 SmallVector<std::unique_ptr<RegisterLiveRange>> regRanges;
87 SmallVector<RegisterLiveRange *> active;
88 for (
auto &op : getOperation()->getRegion(0).getBlocks().front()) {
89 if (!isa<rtg::FixedRegisterOp, rtg::VirtualRegisterOp>(&op))
96 if (
auto regOp = dyn_cast<rtg::VirtualRegisterOp>(&op))
99 if (
auto regOp = dyn_cast<rtg::FixedRegisterOp>(&op))
100 lr.fixedReg = regOp.getReg();
102 for (
auto *user : op.getUsers()) {
103 if (!isa<rtg::InstructionOpInterface, rtg::ValidateOp>(user)) {
104 user->emitError(
"only operations implementing 'InstructionOpInterface' "
105 "and 'rtg.validate' are allowed to use registers");
106 return signalPassFailure();
110 unsigned idx = opIndices.at(user);
111 lr.start = std::min(lr.start, idx);
112 lr.end = std::max(lr.end, idx);
115 regRanges.emplace_back(std::make_unique<RegisterLiveRange>(lr));
123 active.push_back(regRanges.back().get());
127 llvm::sort(regRanges, [](
const auto &a,
const auto &b) {
128 return a->start < b->start || (a->start == b->start && !a->regOp);
131 for (
auto &lr : regRanges) {
140 rtg::RegisterAttrInterface availableReg;
141 for (
auto reg : lr->regOp.getAllowedRegs()) {
142 if (llvm::none_of(active, [&](
auto *r) {
return r->fixedReg ==
reg; })) {
143 availableReg = cast<rtg::RegisterAttrInterface>(reg);
149 ++numRegistersSpilled;
150 lr->regOp->emitError(
151 "need to spill this register, but not supported yet");
152 return signalPassFailure();
155 lr->fixedReg = availableReg;
156 active.push_back(lr.get());
160 for (
auto ®Range : regRanges) {
161 llvm::dbgs() <<
"Start: " << regRange->start <<
", End: " << regRange->end
162 <<
", Selected: " << regRange->fixedReg <<
"\n";
164 llvm::dbgs() <<
"\n";
167 for (
auto ® : regRanges) {
172 IRRewriter rewriter(
reg->regOp);
173 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)