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
0 commit comments