Skip to content

Commit 49397ad

Browse files
committed
feat(codegen): add WIP Segment-Tree register allocator skeleton (disabled by default)
Introduce RegAllocSegmentTree pass skeleton and plumbing: - New files under CodeGen for segment-tree-based RA - Add CMake gate (LLVM_ENABLE_SEG_TRE_RA, default OFF) - (Optional) Macro gate EXPERIMENTAL_SEG_TRE_RA around pass registration Current status: - Does not fully compile when enabled; kept OUT of default build - selectOrSplit/enqueue/dequeue and segment tree ops are stubs - Spiller creation via RequiredAnalyses wired but still under development Design notes: - Store LIS/VRM/MF/MRI as pointers; pass by reference where required - Intend per-physreg data structure for interval storage (no static shared vector) TODO: - Fix pointer/reference consistency across all call sites - Replace static interval buffer with per-physreg containers - Implement incremental segment-tree updates and queries - Implement selectOrSplit and spill heuristics - Add tests; ensure no functional change when gate is OFF Build/usage: - OFF by default; enable with -DLLVM_ENABLE_SEG_TRE_RA=ON - When enabled, use: llc/clang -regalloc=segtre No functional change when LLVM_ENABLE_SEG_TRE_RA=OFF.:
1 parent 9803706 commit 49397ad

24 files changed

+2172
-1
lines changed

llvm/include/llvm/CodeGen/LinkAllCodegenComponents.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,9 @@ namespace {
3434
(void) llvm::createBasicRegisterAllocator();
3535
(void) llvm::createGreedyRegisterAllocator();
3636
(void) llvm::createDefaultPBQPRegisterAllocator();
37-
37+
// 強制把你的 TU 拉進來(引用工廠函式即可)
38+
(void) llvm::createRegAllocSegmentTree();
39+
3840
(void)llvm::createBURRListDAGScheduler(nullptr,
3941
llvm::CodeGenOptLevel::Default);
4042
(void)llvm::createSourceListDAGScheduler(nullptr,

llvm/include/llvm/CodeGen/Passes.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,9 @@ LLVM_ABI FunctionPass *createGreedyRegisterAllocator(RegAllocFilterFunc F);
236236
///
237237
LLVM_ABI FunctionPass *createDefaultPBQPRegisterAllocator();
238238

239+
// 在 Passes.h 中找到其他寄存器分配器的声明,并在附近添加:
240+
LLVM_ABI FunctionPass *createRegAllocSegmentTree();
241+
239242
/// PrologEpilogCodeInserter - This pass inserts prolog and epilog code,
240243
/// and eliminates abstract frame references.
241244
LLVM_ABI extern char &PrologEpilogCodeInserterID;
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
//===- RegAllocSegmentTree.h - Segment Tree Register Allocator --*- C++ -*-==//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file contains the declaration of the SegmentTreeRegisterAllocator class,
10+
// which uses a segment tree data structure to manage register intervals.
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
#ifndef LLVM_CODEGEN_REGALLOCSEGMENTTREE_H
15+
#define LLVM_CODEGEN_REGALLOCSEGMENTTREE_H
16+
17+
#include "RegAllocBase.h"
18+
#include "llvm/CodeGen/LiveInterval.h"
19+
#include "llvm/CodeGen/LiveIntervals.h"
20+
#include "llvm/CodeGen/LiveRangeEdit.h"
21+
#include "llvm/CodeGen/LiveRegMatrix.h"
22+
#include "llvm/CodeGen/LiveStacks.h"
23+
#include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
24+
#include "llvm/CodeGen/MachineDominators.h"
25+
#include "llvm/CodeGen/MachineFunctionPass.h"
26+
#include "llvm/CodeGen/MachineLoopInfo.h"
27+
#include "llvm/CodeGen/VirtRegMap.h"
28+
#include "llvm/ADT/IndexedMap.h"
29+
#include "llvm/ADT/SmallVector.h"
30+
#include <vector>
31+
#include <memory>
32+
33+
namespace llvm {
34+
35+
class LiveIntervals;
36+
class MachineFunction;
37+
class MachineRegisterInfo;
38+
class TargetRegisterInfo;
39+
class VirtRegMap;
40+
41+
/// SegmentTreeRegisterAllocator implements a register allocator by leveraging
42+
/// a segment tree to efficiently track the availability of physical registers
43+
/// across their live ranges.
44+
class RegAllocSegmentTree : public MachineFunctionPass, public RegAllocBase, private LiveRangeEdit::Delegate {
45+
46+
// 非常重要的:用於記錄每個物理暫存器當前的分配區間
47+
// Key: 物理暫存器編號 (PhysReg)
48+
// Value: 一個包含多個(LiveInterval, VirtReg)的列表,表示該物理暫存器上分配了哪些虛擬暫存器及其生命期
49+
// 但注意:一個物理暫存器在同一時間只能被一個虛擬暫存器佔用,所以這實際上是一系列不重疊的區間
50+
// 我們通常用一個按開始時間排序的區間列表來表示一個物理暫存器的使用情況
51+
// 我們將為每個物理暫存器建立一個線段樹
52+
53+
public:
54+
// 线段树节点结构体
55+
struct SegmentTreeNode {
56+
SlotIndex MaxEnd; // 该节点覆盖区间内的最大结束时间
57+
58+
SegmentTreeNode() : MaxEnd(SlotIndex()) {}
59+
};
60+
61+
static char ID; // 静态成员声明
62+
63+
RegAllocSegmentTree();
64+
65+
/// 主要的分配接口,繼承自 MachineFunctionPass
66+
bool runOnMachineFunction(MachineFunction &mf) override;
67+
68+
/// 獲取此分配器的名稱
69+
StringRef getPassName() const override { return "Segment Tree Register Allocator"; }
70+
71+
/// 獲取分析依賴
72+
void getAnalysisUsage(AnalysisUsage &AU) const override {
73+
AU.setPreservesCFG();
74+
AU.addRequired<LiveIntervalsWrapperPass>();
75+
AU.addPreserved<LiveIntervalsWrapperPass>();
76+
AU.addRequired<LiveStacksWrapperLegacy>();
77+
AU.addPreserved<LiveStacksWrapperLegacy>();
78+
AU.addRequired<MachineBlockFrequencyInfoWrapperPass>();
79+
AU.addPreserved<MachineBlockFrequencyInfoWrapperPass>();
80+
AU.addRequired<MachineDominatorTreeWrapperPass>();
81+
AU.addPreserved<MachineDominatorTreeWrapperPass>();
82+
AU.addRequired<MachineLoopInfoWrapperPass>();
83+
AU.addPreserved<MachineLoopInfoWrapperPass>();
84+
AU.addRequired<VirtRegMapWrapperLegacy>();
85+
AU.addPreserved<VirtRegMapWrapperLegacy>();
86+
AU.addRequired<LiveRegMatrixWrapperLegacy>();
87+
AU.addPreserved<LiveRegMatrixWrapperLegacy>();
88+
MachineFunctionPass::getAnalysisUsage(AU);
89+
}
90+
91+
// 我們需要覆蓋這個方法來初始化我們的自定義數據結構
92+
void init(VirtRegMap &vrm, LiveIntervals &lis, LiveRegMatrix &mat);
93+
94+
// 我們需要覆蓋這個方法來實現主要的分配邏輯
95+
void allocatePhysRegs();
96+
97+
// 你自己的 finalize(宣告)
98+
void finalizeAlloc(MachineFunction &MF, LiveIntervals &LIS, VirtRegMap &VRM);
99+
100+
// 你堅持要的同名接口(注意:**不要**寫 override)
101+
void postOptimization(Spiller &VRegSpiller, LiveIntervals &LIS);
102+
protected:
103+
// 必须实现的纯虚函数
104+
Spiller &spiller() override;
105+
void enqueueImpl(const LiveInterval *LI) override;
106+
const LiveInterval *dequeue() override;
107+
MCRegister selectOrSplit(const LiveInterval &VirtReg,
108+
SmallVectorImpl<Register> &splitLVRs) override;
109+
110+
private:
111+
void resetAllocatorState(); // ← 新增
112+
void performSegmentTreeSpecificOptimizations(LiveIntervals &LIS);
113+
void validatePostOptimizationState(LiveIntervals &LIS);
114+
115+
MachineFunction *MF = nullptr;
116+
LiveIntervals *LIS = nullptr;
117+
VirtRegMap *VRM = nullptr;
118+
LiveRegMatrix *LRM = nullptr;
119+
MachineRegisterInfo *MRI = nullptr;
120+
121+
std::unique_ptr<Spiller> VRegSpiller; // Add this line
122+
123+
// 改为动态分配或使用其他数据结构
124+
SmallVector<std::vector<SegmentTreeNode>> PhysRegSegmentTrees;
125+
126+
// 或者,更高效的實現可能使用一個大的線段樹數組,並通過索引來訪問不同暫存器的樹
127+
128+
// 线段树构建辅助函数(递归)
129+
void buildSegmentTree(SegmentTreeNode *tree, unsigned idx,
130+
unsigned l, unsigned r,
131+
const std::vector<SlotIndex> &ends);
132+
133+
// 为物理寄存器构建线段树
134+
void buildSegmentTreeForPhysReg(unsigned PhysReg, const std::vector<SlotIndex>& intervals);
135+
136+
// 查询物理寄存器在指定区间是否可用
137+
bool querySegmentTreeForRange(unsigned PhysReg, SlotIndex Start, SlotIndex End) const;
138+
139+
// 线段树查询辅助函数
140+
bool querySegmentTree(const SegmentTreeNode *tree, unsigned idx,
141+
unsigned tree_l, unsigned tree_r,
142+
SlotIndex query_start, SlotIndex query_end) const;
143+
144+
// 嘗試為給定的虛擬暫存器分配一個物理暫存器
145+
// 返回分配的物理暫存器,若失敗則返回0
146+
unsigned tryAllocateRegister(LiveInterval &VirtReg);
147+
148+
// 檢查物理暫存器是否可用
149+
bool isPhysRegAvailable(unsigned PhysReg, const LiveInterval &VirtReg);
150+
151+
// 溢出處理:當沒有可用的物理暫存器時,選擇一個虛擬暫存器溢出到內存
152+
void spillVirtReg(LiveInterval &VirtReg);
153+
154+
// 更新线段树以反映区间的分配
155+
void updateSegmentTreeForInterval(const LiveInterval &LI, unsigned PhysReg);
156+
157+
// 更新物理寄存器的线段树(分配区间后)
158+
void updateSegmentTreeForPhysReg(unsigned PhysReg, SlotIndex Start, SlotIndex End);
159+
};
160+
161+
// 創建SegmentTreeRegisterAllocator實例的函數
162+
FunctionPass *createRegAllocSegmentTree();
163+
164+
} // end namespace llvm
165+
166+
#endif // LLVM_CODEGEN_REGALLOCSEGMENTTREE_H

llvm/lib/CodeGen/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ add_llvm_component_library(LLVMCodeGen
187187
RegAllocGreedy.cpp
188188
RegAllocPBQP.cpp
189189
RegAllocPriorityAdvisor.cpp
190+
RegAllocSegmentTree.cpp
190191
RegAllocScore.cpp
191192
RegisterClassInfo.cpp
192193
RegisterCoalescer.cpp

0 commit comments

Comments
 (0)