Skip to content

Commit 002d28f

Browse files
committed
Add LLVM Segment Tree Register Allocator implementation
- Implement segment tree-based register allocator for LLVM - Features coordinate compression and lazy propagation - Add interference checking using interval tree queries - Include performance benchmarking against RAGreedy - Currently 6.7x slower than baseline (experimental research)
1 parent 9ebc02b commit 002d28f

File tree

4 files changed

+636
-283
lines changed

4 files changed

+636
-283
lines changed

llvm/include/llvm/CodeGen/RegAllocSegmentTree.h

Lines changed: 49 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include <memory>
3232
#include <utility>
3333
#include <algorithm>
34+
#include <queue>
3435

3536
namespace llvm {
3637

@@ -40,99 +41,73 @@ class MachineRegisterInfo;
4041
class TargetRegisterInfo;
4142
class VirtRegMap;
4243

43-
/// SegmentTreeRegisterAllocator implements a register allocator by leveraging
44-
/// a segment tree to efficiently track the availability of physical registers
45-
/// across their live ranges.
46-
class RegAllocSegmentTree : public MachineFunctionPass, public RegAllocBase, private LiveRangeEdit::Delegate {
47-
48-
// 非常重要的:用於記錄每個物理暫存器當前的分配區間
49-
// Key: 物理暫存器編號 (PhysReg)
50-
// Value: 一個包含多個(LiveInterval, VirtReg)的列表,表示該物理暫存器上分配了哪些虛擬暫存器及其生命期
51-
// 但注意:一個物理暫存器在同一時間只能被一個虛擬暫存器佔用,所以這實際上是一系列不重疊的區間
52-
// 我們通常用一個按開始時間排序的區間列表來表示一個物理暫存器的使用情況
53-
// 我們將為每個物理暫存器建立一個線段樹
54-
44+
class RegAllocSegmentTree : public MachineFunctionPass,
45+
public RegAllocBase,
46+
private LiveRangeEdit::Delegate {
5547
public:
56-
// 线段树节点结构体
57-
struct SegmentTreeNode {
58-
SlotIndex MaxEnd; // 该节点覆盖区间内的最大结束时间
59-
60-
SegmentTreeNode() : MaxEnd(SlotIndex()) {}
61-
};
62-
6348
static char ID; // 静态成员声明
6449

6550
RegAllocSegmentTree();
6651

67-
/// 主要的分配接口,繼承自 MachineFunctionPass
52+
// MachineFunctionPass interface
6853
bool runOnMachineFunction(MachineFunction &mf) override;
69-
70-
/// 獲取此分配器的名稱
7154
StringRef getPassName() const override { return "Segment Tree Register Allocator"; }
7255

7356
/// 獲取分析依賴
74-
void getAnalysisUsage(AnalysisUsage &AU) const override {
75-
AU.setPreservesCFG();
76-
AU.addRequired<SlotIndexesWrapperPass>();
77-
AU.addPreserved<SlotIndexesWrapperPass>();
78-
AU.addRequired<LiveIntervalsWrapperPass>();
79-
AU.addPreserved<LiveIntervalsWrapperPass>();
80-
AU.addRequired<LiveStacksWrapperLegacy>();
81-
AU.addPreserved<LiveStacksWrapperLegacy>();
82-
AU.addRequired<MachineBlockFrequencyInfoWrapperPass>();
83-
AU.addPreserved<MachineBlockFrequencyInfoWrapperPass>();
84-
AU.addRequired<MachineDominatorTreeWrapperPass>();
85-
AU.addPreserved<MachineDominatorTreeWrapperPass>();
86-
AU.addRequired<MachineLoopInfoWrapperPass>();
87-
AU.addPreserved<MachineLoopInfoWrapperPass>();
88-
AU.addRequired<VirtRegMapWrapperLegacy>();
89-
AU.addPreserved<VirtRegMapWrapperLegacy>();
90-
AU.addRequired<LiveRegMatrixWrapperLegacy>();
91-
AU.addPreserved<LiveRegMatrixWrapperLegacy>();
92-
MachineFunctionPass::getAnalysisUsage(AU);
93-
}
9457

9558
// 我們需要覆蓋這個方法來初始化我們的自定義數據結構
9659
void init(VirtRegMap &vrm, LiveIntervals &lis, LiveRegMatrix &mat);
9760

98-
// 我們需要覆蓋這個方法來實現主要的分配邏輯
99-
void allocatePhysRegs();
100-
10161
// 你自己的 finalize(宣告)
10262
void finalizeAlloc(MachineFunction &MF, LiveIntervals &LIS, VirtRegMap &VRM) const;
10363

64+
#ifndef NDEBUG
65+
bool verifyAllocation(MachineFunction &MF, LiveIntervals &LIS, VirtRegMap &VRM);
66+
#endif
67+
10468
// 你堅持要的同名接口(注意:**不要**寫 override)
10569
void postOptimization(Spiller &VRegSpiller, LiveIntervals &LIS);
106-
protected:
107-
// 必须实现的纯虚函数
108-
Spiller &spiller() override;
109-
void enqueueImpl(const LiveInterval *LI) override;
110-
const LiveInterval *dequeue() override;
111-
MCRegister selectOrSplit(const LiveInterval &VirtReg,
112-
SmallVectorImpl<Register> &splitLVRs) override;
11370

11471
private:
72+
// Timer group constants
73+
static const char TimerGroupName[];
74+
static const char TimerGroupDescription[];
75+
76+
// Performance statistics
77+
mutable unsigned NumInterferenceChecks = 0;
78+
mutable unsigned NumSegTreeUpdates = 0;
79+
mutable unsigned NumCoordRebuilds = 0;
80+
mutable unsigned NumAllocAttempts = 0;
81+
mutable unsigned NumSpills = 0;
82+
83+
// Convenient shortcuts.
84+
using PQueue = std::priority_queue<std::pair<unsigned, unsigned>>;
85+
using SmallLISet = SmallSetVector<const LiveInterval *, 4>;
86+
11587
void resetAllocatorState(); // ← 新增
88+
void precomputeAllCoordinates();
11689
void performSegmentTreeSpecificOptimizations(LiveIntervals &LIS);
11790
void validatePostOptimizationState(LiveIntervals &LIS);
11891

11992
MachineFunction *MF = nullptr;
93+
94+
// Shortcuts to some useful interface.
95+
const TargetInstrInfo *TII = nullptr;
96+
12097
LiveIntervals *LIS = nullptr;
12198
VirtRegMap *VRM = nullptr;
12299
LiveRegMatrix *LRM = nullptr;
123100
MachineRegisterInfo *MRI = nullptr;
101+
const TargetRegisterInfo *TRI = nullptr;
124102

125103
RegisterClassInfo RCI;
126104

127-
std::unique_ptr<Spiller> VRegSpiller; // Add this line
105+
std::unique_ptr<Spiller> SpillerInstance; // Add this line
128106

129107
// 工作佇列與去重集合
130-
llvm::SmallVector<const LiveInterval*, 64> WorkQ;
108+
llvm::SmallVector<const LiveInterval*, 64> CurQueue;
131109
llvm::SmallDenseSet<unsigned, 64> InQ; // 記 vreg id,避免重複排入
132110

133-
// Legacy demo per-physreg trees (kept for compatibility paths).
134-
SmallVector<std::vector<SegmentTreeNode>> PhysRegSegmentTrees;
135-
136111
// Bookkeeping of allocated intervals per physical register (for rebuild).
137112
std::vector<std::vector<std::pair<SlotIndex, SlotIndex>>> PhysRegIntervals;
138113

@@ -166,22 +141,6 @@ class RegAllocSegmentTree : public MachineFunctionPass, public RegAllocBase, pri
166141
// 可放檢查(含別名):任一段 maxCover>0 就不可放
167142
bool canPlaceOnPhysReg(unsigned PhysReg, const LiveInterval &LI) const;
168143

169-
// 线段树构建辅助函数(递归)
170-
void buildSegmentTree(SegmentTreeNode *tree, unsigned idx,
171-
unsigned l, unsigned r,
172-
const std::vector<SlotIndex> &ends);
173-
174-
// 为物理寄存器构建线段树
175-
void buildSegmentTreeForPhysReg(unsigned PhysReg, const std::vector<SlotIndex>& intervals);
176-
177-
// 查询物理寄存器在指定区间是否可用
178-
bool querySegmentTreeForRange(unsigned PhysReg, SlotIndex Start, SlotIndex End) const;
179-
180-
// 线段树查询辅助函数
181-
bool querySegmentTree(const SegmentTreeNode *tree, unsigned idx,
182-
unsigned tree_l, unsigned tree_r,
183-
SlotIndex query_start, SlotIndex query_end) const;
184-
185144
// 嘗試為給定的虛擬暫存器分配一個物理暫存器
186145
// 返回分配的物理暫存器,若失敗則返回0
187146
unsigned tryAllocateRegister(LiveInterval &VirtReg);
@@ -197,11 +156,27 @@ class RegAllocSegmentTree : public MachineFunctionPass, public RegAllocBase, pri
197156

198157
// 更新物理寄存器的线段树(分配区间后)
199158
void updateSegmentTreeForPhysReg(unsigned PhysReg, SlotIndex Start, SlotIndex End);
159+
160+
// 清理失败的虚拟寄存器
161+
void cleanupFailedVReg(Register FailedVReg, unsigned Depth,
162+
SmallVectorImpl<Register> &SplitRegs);
163+
164+
// 找到合適的拆分點
165+
SlotIndex findSplitPoint(const LiveInterval &LI);
166+
public:
167+
// RegAllocBase interface
168+
Spiller &spiller() override { return *SpillerInstance; };
169+
void enqueueImpl(const LiveInterval *LI) override;
170+
const LiveInterval *dequeue() override;
171+
MCRegister selectOrSplit(const LiveInterval &VirtReg,
172+
SmallVectorImpl<Register> &splitLVRs) override;
173+
174+
void getAnalysisUsage(AnalysisUsage &AU) const override;
200175
};
201176

202177
// 創建SegmentTreeRegisterAllocator實例的函數
203178
FunctionPass *createRegAllocSegmentTree();
204179

205180
} // end namespace llvm
206181

207-
#endif // LLVM_CODEGEN_REGALLOCSEGMENTTREE_H
182+
#endif // LLVM_CODEGEN_REGALLOCSEGMENTTREE_H

llvm/include/llvm/InitializePasses.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,7 @@ initializeRegAllocEvictionAdvisorAnalysisLegacyPass(PassRegistry &);
271271
LLVM_ABI void initializeRegAllocFastPass(PassRegistry &);
272272
LLVM_ABI void
273273
initializeRegAllocPriorityAdvisorAnalysisLegacyPass(PassRegistry &);
274+
LLVM_ABI void initializeRegAllocSegmentTreePass(PassRegistry&);
274275
LLVM_ABI void initializeRegAllocScoringPass(PassRegistry &);
275276
LLVM_ABI void initializeRegBankSelectPass(PassRegistry &);
276277
LLVM_ABI void initializeRegToMemWrapperPassPass(PassRegistry &);

llvm/lib/CodeGen/CodeGen.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ void llvm::initializeCodeGen(PassRegistry &Registry) {
113113
initializeRABasicPass(Registry);
114114
initializeRAGreedyLegacyPass(Registry);
115115
initializeRegAllocFastPass(Registry);
116+
initializeRegAllocSegmentTreePass(Registry); // Add this line
116117
initializeRegUsageInfoCollectorLegacyPass(Registry);
117118
initializeRegUsageInfoPropagationLegacyPass(Registry);
118119
initializeRegisterCoalescerLegacyPass(Registry);

0 commit comments

Comments
 (0)