Skip to content

Commit 9ebc02b

Browse files
committed
[RegAlloc] WIP: prototype segment tree register allocator
1 parent de01e65 commit 9ebc02b

File tree

2 files changed

+120
-113
lines changed

2 files changed

+120
-113
lines changed

llvm/include/llvm/CodeGen/RegAllocSegmentTree.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ class RegAllocSegmentTree : public MachineFunctionPass, public RegAllocBase, pri
9999
void allocatePhysRegs();
100100

101101
// 你自己的 finalize(宣告)
102-
void finalizeAlloc(MachineFunction &MF, LiveIntervals &LIS, VirtRegMap &VRM);
102+
void finalizeAlloc(MachineFunction &MF, LiveIntervals &LIS, VirtRegMap &VRM) const;
103103

104104
// 你堅持要的同名接口(注意:**不要**寫 override)
105105
void postOptimization(Spiller &VRegSpiller, LiveIntervals &LIS);
@@ -122,8 +122,14 @@ class RegAllocSegmentTree : public MachineFunctionPass, public RegAllocBase, pri
122122
LiveRegMatrix *LRM = nullptr;
123123
MachineRegisterInfo *MRI = nullptr;
124124

125+
RegisterClassInfo RCI;
126+
125127
std::unique_ptr<Spiller> VRegSpiller; // Add this line
126128

129+
// 工作佇列與去重集合
130+
llvm::SmallVector<const LiveInterval*, 64> WorkQ;
131+
llvm::SmallDenseSet<unsigned, 64> InQ; // 記 vreg id,避免重複排入
132+
127133
// Legacy demo per-physreg trees (kept for compatibility paths).
128134
SmallVector<std::vector<SegmentTreeNode>> PhysRegSegmentTrees;
129135

llvm/lib/CodeGen/RegAllocSegmentTree.cpp

Lines changed: 113 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ bool RegAllocSegmentTree::runOnMachineFunction(MachineFunction &MF) {
115115
// 主要的分配循环
116116
bool AllocComplete = false;
117117
unsigned Round = 0;
118-
const unsigned MaxRounds = 5; // 防止无限循环
118+
const unsigned MaxRounds = 100; // 防止无限循环
119119

120120
while (!AllocComplete && Round < MaxRounds) {
121121
LLVM_DEBUG(dbgs() << " Segment Tree Regalloc round " << Round << ":\n");
@@ -126,6 +126,8 @@ bool RegAllocSegmentTree::runOnMachineFunction(MachineFunction &MF) {
126126

127127
// 尝试分配所有虚拟寄存器
128128
bool HasSpills = false;
129+
bool HasUnAllocated = false;
130+
129131
for (LiveInterval *LI : VRegsToAlloc) {
130132
unsigned VirtReg = LI->reg();
131133
if (VRM->hasPhys(VirtReg)) // 可能已经通过合并分配了
@@ -139,19 +141,22 @@ bool RegAllocSegmentTree::runOnMachineFunction(MachineFunction &MF) {
139141
VRM->assignVirt2Phys(VirtReg, PhysReg);
140142
updateSegmentTreeForInterval(*LI, PhysReg);
141143
} else {
142-
// 分配失败,需要溢出
143-
HasSpills = true;
144-
spillVirtReg(*LI);
144+
// 尝试溢出
145+
if (LI->isSpillable()) {
146+
HasSpills = true;
147+
spillVirtReg(*LI);
148+
} else {
149+
HasUnAllocated = true;
150+
LLVM_DEBUG(dbgs() << "Virtual register " << VirtReg
151+
<< " cannot be spilled or allocated\n");
152+
}
145153
}
146154
}
147155

148-
// 如果没有溢出,分配完成
149-
if (!HasSpills) {
150-
AllocComplete = true;
151-
} else {
152-
// 处理溢出后,可能需要重新计算LiveIntervals并重新分配
153-
// 这里需要实现溢出后的处理逻辑
154-
156+
// 检查是否完成分配
157+
AllocComplete = !HasSpills && !HasUnAllocated;
158+
159+
if (!AllocComplete) {
155160
// 重新收集需要分配的虚拟寄存器
156161
VRegsToAlloc.clear();
157162
for (unsigned i = 0, e = MF.getRegInfo().getNumVirtRegs(); i != e; ++i) {
@@ -161,13 +166,17 @@ bool RegAllocSegmentTree::runOnMachineFunction(MachineFunction &MF) {
161166
LiveInterval *LI = &LIS->getInterval(Reg);
162167
if (LI->empty())
163168
continue;
164-
VRegsToAlloc.push_back(LI);
169+
// 只收集尚未分配的寄存器
170+
if (!VRM->hasPhys(Reg)) {
171+
VRegsToAlloc.push_back(LI);
172+
}
173+
}
174+
175+
// 如果没有需要处理的寄存器,但AllocComplete为false,这是一个错误
176+
if (VRegsToAlloc.empty() && !AllocComplete) {
177+
LLVM_DEBUG(dbgs() << "Warning: No registers to process but allocation not complete\n");
178+
AllocComplete = true; // 强制完成
165179
}
166-
167-
// 重新排序
168-
llvm::sort(VRegsToAlloc, [](const LiveInterval *A, const LiveInterval *B) {
169-
return A->getSize() > B->getSize();
170-
});
171180
}
172181

173182
++Round;
@@ -194,12 +203,26 @@ Spiller &RegAllocSegmentTree::spiller() {
194203
}
195204

196205
void RegAllocSegmentTree::enqueueImpl(const LiveInterval *LI) {
197-
// 简单实现:暂时不做任何操作
206+
207+
if (!LI) return;
208+
unsigned V = LI->reg();
209+
if (!V) return;
210+
// 不處理已經空掉或僅 debug 定義的 vreg
211+
if (MF && MF->getRegInfo().reg_nodbg_empty(V)) return;
212+
213+
// 只有第一次進佇列會插入成功
214+
if (InQ.insert(V).second) {
215+
WorkQ.push_back(LI);
216+
LLVM_DEBUG(dbgs() << " enqueue vreg " << V << " (queue size=" << WorkQ.size() << ")\n");
217+
}
198218
}
199219

200220
const LiveInterval *RegAllocSegmentTree::dequeue() {
201-
// 返回nullptr或简单实现
202-
return nullptr;
221+
if (WorkQ.empty()) return nullptr;
222+
const LiveInterval *LI = WorkQ.back();
223+
WorkQ.pop_back();
224+
if (LI) InQ.erase(LI->reg());
225+
return LI;
203226
}
204227

205228
MCRegister RegAllocSegmentTree::selectOrSplit(const LiveInterval &VirtReg,
@@ -238,13 +261,8 @@ void RegAllocSegmentTree::init(VirtRegMap &vrm, LiveIntervals &lis,
238261

239262
this->MRI = &MF->getRegInfo();
240263

241-
// 2. 為每個暫存器類別初始化線段樹
242-
// 這是一個簡化的示例。實際實現中,您需要遍歷所有可分配的物理暫存器
243-
for (unsigned RCId = 0; RCId < TRI->getNumRegClasses(); ++RCId) {
244-
// 獲取該暫存器類別中的所有物理暫存器
245-
// 初始化對應的線段樹...
246-
// PhysRegSegmentTrees[RCId].resize(...);
247-
}
264+
// 确保保留寄存器信息已冻结
265+
MRI->freezeReservedRegs();
248266

249267
LLVM_DEBUG(dbgs() << "Initializing Segment Tree Register Allocator with "
250268
<< NumPhysRegs << " physical registers\n");
@@ -319,6 +337,12 @@ unsigned RegAllocSegmentTree::tryAllocateRegister(LiveInterval &VirtReg) {
319337
LLVM_DEBUG(dbgs() << "Skipping physreg 0\n");
320338
continue;
321339
}
340+
341+
// 检查该物理寄存器是否是保留寄存器
342+
if (MRI->isReserved(PhysReg)) {
343+
LLVM_DEBUG(dbgs() << "Skipping reserved physreg " << PhysReg << "\n");
344+
continue;
345+
}
322346

323347
// 检查该物理寄存器是否在VirtReg的整个生命期内都可用
324348
if (isPhysRegAvailable(PhysReg, VirtReg)) {
@@ -562,114 +586,88 @@ void RegAllocSegmentTree::segtreeBuild(unsigned PhysReg) {
562586
}
563587

564588
void RegAllocSegmentTree::spillVirtReg(LiveInterval &VirtReg) {
565-
assert(MF && LIS && VRM &&
566-
"RA pointers must be initialized before spilling");
589+
assert(MF && LIS && VRM);
590+
LLVM_DEBUG(dbgs() << "Spilling vreg " << VirtReg.reg() << '\n');
567591

568-
LLVM_DEBUG(dbgs() << "Spilling virtual register: " << VirtReg.reg() << '\n');
569-
570-
// Create a LiveRangeEdit object for the virtual register
571592
SmallVector<Register, 4> NewVRegs;
572593
LiveRangeEdit LRE(&VirtReg, NewVRegs, *MF, *LIS, VRM, this, &DeadRemats);
573-
574-
// Use the spiller with the LiveRangeEdit object
594+
575595
spiller().spill(LRE);
576-
577-
// 將新生成的虛擬寄存器加入隊列
578-
for (Register NewVReg : NewVRegs) {
579-
if (!LIS->hasInterval(NewVReg))
580-
continue;
581-
LiveInterval &NewLI = LIS->getInterval(NewVReg);
596+
597+
for (Register NV : NewVRegs) {
598+
if (!LIS->hasInterval(NV)) continue;
599+
LiveInterval &NewLI = LIS->getInterval(NV);
582600
enqueue(&NewLI);
583601
}
584602
}
585603

586-
void RegAllocSegmentTree::finalizeAlloc(MachineFunction &MF,
587-
LiveIntervals &LIS,
588-
VirtRegMap &VRM) {
589-
// 设置机器寄存器信息指针
590-
MRI = &MF.getRegInfo();
604+
void RegAllocSegmentTree::finalizeAlloc(MachineFunction &MF,
605+
LiveIntervals &LIS,
606+
VirtRegMap &VRM) const {
607+
MachineRegisterInfo &MRI = MF.getRegInfo();
591608

592-
// 处理空区间(没有实际生命期的虚拟寄存器)
593-
for (unsigned i = 0, e = MF.getRegInfo().getNumVirtRegs(); i != e; ++i) {
594-
unsigned Reg = Register::index2VirtReg(i);
595-
if (MF.getRegInfo().reg_nodbg_empty(Reg))
609+
LLVM_DEBUG(dbgs() << "Finalizing allocation - checking all virtual registers\n");
610+
611+
// 處理所有虛擬寄存器,確保都有分配
612+
for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
613+
Register Reg = Register::index2VirtReg(I);
614+
if (MRI.reg_nodbg_empty(Reg))
615+
continue;
616+
617+
// 如果已經分配,跳過
618+
if (VRM.hasPhys(Reg))
596619
continue;
620+
621+
// 強制分配策略
622+
LiveInterval &LI = LIS.getInterval(Reg);
623+
const TargetRegisterClass &RC = *MRI.getRegClass(Reg);
597624

598-
LiveInterval *LI = &LIS.getInterval(Reg);
599-
if (LI->empty() && !VRM.hasPhys(Reg)) {
600-
// 为空区间分配任意可用的物理寄存器
601-
const TargetRegisterClass *RC = MF.getRegInfo().getRegClass(Reg);
602-
if (RC->getNumRegs() > 0) {
603-
// 选择第一个可用的物理寄存器
604-
MCRegister PhysReg = *RC->begin();
605-
VRM.assignVirt2Phys(Reg, PhysReg);
606-
LLVM_DEBUG(dbgs() << "Assigned empty interval " << Reg
607-
<< " to physical register " << PhysReg << "\n");
625+
LLVM_DEBUG(dbgs() << "Force-allocating unassigned register "
626+
<< printReg(Reg, TRI) << "\n");
627+
628+
// 尋找第一個可用的物理寄存器
629+
Register PReg = 0;
630+
ArrayRef<MCPhysReg> Order = RC.getRawAllocationOrder(MF);
631+
for (MCPhysReg CandidateReg : Order) {
632+
if (CandidateReg != 0 && !VRM.getRegInfo().isReserved(CandidateReg)) {
633+
PReg = CandidateReg;
634+
break;
608635
}
609636
}
637+
638+
// 如果仍然找不到,使用第一個非零寄存器(即使是保留寄存器)
639+
if (PReg == 0 && !Order.empty()) {
640+
PReg = Order[0];
641+
}
642+
643+
if (PReg != 0) {
644+
VRM.assignVirt2Phys(Reg, PReg);
645+
LLVM_DEBUG(dbgs() << "Force-assigned " << printReg(Reg, TRI)
646+
<< " to " << printReg(PReg, TRI) << "\n");
647+
} else {
648+
// 這應該永遠不會發生
649+
llvm_unreachable("Cannot find any physical register for virtual register");
650+
}
610651
}
611652

612-
// 清理线段树数据结构
613-
PhysRegSegmentTrees.clear();
614-
615-
// 验证分配结果
653+
// 驗證所有虛擬寄存器都已分配
616654
LLVM_DEBUG({
617-
bool HasErrors = false;
618-
619-
// 检查所有虚拟寄存器是否都已分配
620-
for (unsigned i = 0, e = MF.getRegInfo().getNumVirtRegs(); i != e; ++i) {
621-
unsigned Reg = Register::index2VirtReg(i);
622-
if (MF.getRegInfo().reg_nodbg_empty(Reg))
655+
bool AllAllocated = true;
656+
for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; ++I) {
657+
Register Reg = Register::index2VirtReg(I);
658+
if (MRI.reg_nodbg_empty(Reg))
623659
continue;
624660

625-
LiveInterval *LI = &LIS.getInterval(Reg);
626-
if (!LI->empty() && !VRM.hasPhys(Reg)) {
627-
dbgs() << "Error: Virtual register " << Reg
628-
<< " was not allocated!\n";
629-
HasErrors = true;
661+
if (!VRM.hasPhys(Reg)) {
662+
dbgs() << "ERROR: Virtual register " << Reg << " still not allocated!\n";
663+
AllAllocated = false;
630664
}
631665
}
632666

633-
// 检查物理寄存器冲突
634-
for (unsigned i = 0, e = MF.getRegInfo().getNumVirtRegs(); i != e; ++i) {
635-
unsigned Reg = Register::index2VirtReg(i);
636-
if (!VRM.hasPhys(Reg) || MF.getRegInfo().reg_nodbg_empty(Reg))
637-
continue;
638-
639-
MCRegister PhysReg = VRM.getPhys(Reg);
640-
LiveInterval *LI = &LIS.getInterval(Reg);
641-
642-
// 检查是否有其他虚拟寄存器分配到同一个物理寄存器
643-
for (unsigned j = i + 1; j < e; ++j) {
644-
unsigned OtherReg = Register::index2VirtReg(j);
645-
if (!VRM.hasPhys(OtherReg) || MF.getRegInfo().reg_nodbg_empty(OtherReg))
646-
continue;
647-
648-
if (VRM.getPhys(OtherReg) == PhysReg) {
649-
LiveInterval *OtherLI = &LIS.getInterval(OtherReg);
650-
651-
// 检查区间是否重叠
652-
if (LI->overlaps(*OtherLI)) {
653-
dbgs() << "Error: Virtual registers " << Reg << " and " << OtherReg
654-
<< " both assigned to physical register " << PhysReg
655-
<< " with overlapping live ranges!\n";
656-
HasErrors = true;
657-
}
658-
}
659-
}
660-
}
661-
662-
if (!HasErrors) {
663-
dbgs() << "Segment Tree allocation successfully completed for "
664-
<< MF.getName() << "\n";
665-
} else {
666-
dbgs() << "Segment Tree allocation completed with errors for "
667-
<< MF.getName() << "\n";
667+
if (AllAllocated) {
668+
dbgs() << "SUCCESS: All virtual registers have been allocated\n";
668669
}
669670
});
670-
671-
// 重置分配器状态,为下一个函数做准备
672-
resetAllocatorState();
673671
}
674672

675673
void RegAllocSegmentTree::resetAllocatorState() {
@@ -680,6 +678,9 @@ void RegAllocSegmentTree::resetAllocatorState() {
680678
PRTree.clear();
681679
DeadRemats.clear();
682680
FailedVRegs.clear();
681+
682+
WorkQ.clear();
683+
InQ.clear();
683684
}
684685

685686
void RegAllocSegmentTree::postOptimization(Spiller &VRegSpiller, LiveIntervals &LIS) {

0 commit comments

Comments
 (0)