1- // ===- RegAllocSegmentTree.h - Segment Tree Register Allocator -- *- C++ -*-==//
1+ // ===- RegAllocSegmentTree.h - RA segtree scaffold -------------- *- C++ -*-= ==//
22//
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.
3+ // This file declares createRegAllocSegmentTree() factory (scaffold only).
114//
125// ===----------------------------------------------------------------------===//
136
147#ifndef LLVM_CODEGEN_REGALLOCSEGMENTTREE_H
158#define LLVM_CODEGEN_REGALLOCSEGMENTTREE_H
169
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/RegAllocPriorityAdvisor.h"
28- #include " llvm/CodeGen/SlotIndexes.h"
29- #include " llvm/CodeGen/VirtRegMap.h"
30- #include " llvm/ADT/IndexedMap.h"
31- #include " llvm/ADT/SmallSet.h"
32- #include " llvm/ADT/SmallVector.h"
33- #include " llvm/ADT/SetVector.h"
34- #include " llvm/Support/Timer.h"
35- #include < vector>
36- #include < memory>
37- #include < utility>
38- #include < algorithm>
39- #include < queue>
40-
4110namespace llvm {
11+ class FunctionPass ;
4212
43- // 在任何 class 定義之前加入這些 type aliases
44- using SmallVirtRegSet = SmallSet<Register, 16 >;
45- using RecoloringStack = SmallVector<std::pair<const LiveInterval*, MCRegister>, 8 >;
46-
47- class LiveIntervals ;
48- class MachineFunction ;
49- class MachineRegisterInfo ;
50- class TargetRegisterInfo ;
51- class VirtRegMap ;
52-
53- // / Segment Tree Register Allocator
54- // /
55- // / This register allocator uses a segment tree data structure to efficiently
56- // / detect conflicts between live intervals and physical registers.
57- class RegAllocSegmentTree : public MachineFunctionPass ,
58- public RegAllocBase,
59- private LiveRangeEdit::Delegate {
60- public:
61- // Interface to eviction advisers
62- // / Track allocation stage and eviction loop prevention during allocation.
63- class ExtraRegInfo final {
64- // RegInfo - Keep additional information about each live range.
65- struct RegInfo {
66- LiveRangeStage Stage = RS_New;
67-
68- // Cascade - Eviction loop prevention. See
69- // canEvictInterferenceBasedOnCost().
70- unsigned Cascade = 0 ;
71-
72- RegInfo () = default ;
73- };
74-
75- IndexedMap<RegInfo, VirtReg2IndexFunctor> Info;
76- unsigned NextCascade = 1 ;
77-
78- public:
79- ExtraRegInfo () {}
80- ExtraRegInfo (const ExtraRegInfo &) = delete ;
81-
82- LiveRangeStage getStage (Register Reg) const { return Info[Reg].Stage ; }
83-
84- LiveRangeStage getStage (const LiveInterval &VirtReg) const {
85- return getStage (VirtReg.reg ());
86- }
87-
88- void setStage (Register Reg, LiveRangeStage Stage) {
89- Info.grow (Reg.id ());
90- Info[Reg].Stage = Stage;
91- }
92-
93- void setStage (const LiveInterval &VirtReg, LiveRangeStage Stage) {
94- setStage (VirtReg.reg (), Stage);
95- }
96-
97- // / Return the current stage of the register, if present, otherwise
98- // / initialize it and return that.
99- LiveRangeStage getOrInitStage (Register Reg) {
100- Info.grow (Reg.id ());
101- return getStage (Reg);
102- }
103-
104- unsigned getCascade (Register Reg) const { return Info[Reg].Cascade ; }
105-
106- void setCascade (Register Reg, unsigned Cascade) {
107- Info.grow (Reg.id ());
108- Info[Reg].Cascade = Cascade;
109- }
110-
111- unsigned getOrAssignNewCascade (Register Reg) {
112- unsigned Cascade = getCascade (Reg);
113- if (!Cascade) {
114- Cascade = NextCascade++;
115- setCascade (Reg, Cascade);
116- }
117- return Cascade;
118- }
119-
120- unsigned getCascadeOrCurrentNext (Register Reg) const {
121- unsigned Cascade = getCascade (Reg);
122- if (!Cascade)
123- Cascade = NextCascade;
124- return Cascade;
125- }
126-
127- template <typename Iterator>
128- void setStage (Iterator Begin, Iterator End, LiveRangeStage NewStage) {
129- for (; Begin != End; ++Begin) {
130- Register Reg = *Begin;
131- Info.grow (Reg.id ());
132- if (Info[Reg].Stage == RS_New)
133- Info[Reg].Stage = NewStage;
134- }
135- }
136- void LRE_DidCloneVirtReg (Register New, Register Old);
137- };
138-
139- public:
140-
141- static char ID; // 静态成员声明
142-
143- RegAllocSegmentTree ();
144- ~RegAllocSegmentTree () override ;
145-
146- // MachineFunctionPass interface
147- bool runOnMachineFunction (MachineFunction &mf) override ;
148- StringRef getPassName () const override { return " Segment Tree Register Allocator" ; }
149-
150- // / 獲取分析依賴
151- void getAnalysisUsage (AnalysisUsage &AU) const override ;
152-
153- // 我們需要覆蓋這個方法來初始化我們的自定義數據結構
154- void init (VirtRegMap &vrm, LiveIntervals &lis, LiveRegMatrix &mat);
155-
156- // / Finalize allocation and verify results
157- void finalizeAlloc (MachineFunction &MF, LiveIntervals &LIS, VirtRegMap &VRM) const ;
158-
159- // 你堅持要的同名接口(注意:**不要**寫 override)
160- void postOptimization (Spiller &VRegSpiller, LiveIntervals &LIS);
161-
162- #ifndef NDEBUG
163- bool verifyAllocation (MachineFunction &MF, LiveIntervals &LIS,
164- VirtRegMap &VRM);
165- #endif
166-
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- MCRegister selectOrSplitAdvanced (const LiveInterval &VirtReg,
174- SmallVectorImpl<Register> &splitLVRs);
175-
176- private:
177- // Convenient shortcuts.
178- using PQueue = std::priority_queue<std::pair<unsigned , unsigned >>;
179- using SmallLISet = SmallSetVector<const LiveInterval *, 4 >;
180-
181- MCRegister selectOrSplitImpl (const LiveInterval &,
182- SmallVectorImpl<Register> &, SmallVirtRegSet &,
183- RecoloringStack &, unsigned = 0 );
184-
185- void enqueue (PQueue &CurQueue, const LiveInterval *LI);
186- const LiveInterval *dequeue (PQueue &CurQueue);
187-
188- // Timer group constants
189- static const char TimerGroupName[];
190- static const char TimerGroupDescription[];
191-
192- // Timer group
193- std::unique_ptr<TimerGroup> TimerGroupObj;
194- // Timers for different phases
195- std::unique_ptr<Timer> PrecomputeTimer;
196- std::unique_ptr<Timer> AllocationTimer;
197- std::unique_ptr<Timer> SpillTimer;
198- std::unique_ptr<Timer> CleanupTimer;
199- std::unique_ptr<Timer> PostOptTimer;
200- std::unique_ptr<Timer> SegTreeUpdateTimer;
201- std::unique_ptr<Timer> SegTreeQueryTimer;
202- std::unique_ptr<Timer> GlobalSplitTimer;
203- std::unique_ptr<Timer> LocalSplitTimer;
204- std::unique_ptr<Timer> RegionSplitTimer;
205- std::unique_ptr<Timer> BlockSplitTimer;
206-
207- double TotalPrecomputeTime = 0 ;
208- double TotalAllocationTime = 0 ;
209- double TotalSpillTime = 0 ;
210- double TotalCleanupTime = 0 ;
211- double TotalPostOptTime = 0 ;
212- double TotalSegTreeUpdateTime = 0 ;
213- double TotalSegTreeQueryTime = 0 ;
214-
215- // Performance statistics
216- mutable unsigned NumInterferenceChecks = 0 ;
217- mutable unsigned NumSegTreeUpdates = 0 ;
218- mutable unsigned NumSegTreeUpdatesReal = 0 ;
219- mutable unsigned NumCoordRebuilds = 0 ;
220- mutable unsigned NumAllocAttempts = 0 ;
221- mutable unsigned NumSpills = 0 ;
222-
223- uint64_t NumSegTreeUpdatesRealLocal = 0 ; // 每個函式的成功更新次數
224-
225- unsigned TotalAllocAttempts = 0 ;
226- unsigned TotalInterferenceChecks = 0 ;
227- unsigned TotalSegTreeUpdates = 0 ;
228- unsigned TotalSegTreeUpdatesReal = 0 ;
229- unsigned TotalCoordRebuilds = 0 ;
230- unsigned TotalSpills = 0 ;
231-
232- void resetAllocatorState (); // ← 新增
233-
234- // [NEW] 是否啟用 precompute(由 .cpp 的 cl::opt 注入)
235- bool UsePrecompute = true ;
236-
237- // [NEW] 讓 runOnMachineFunction 能用同一個入口呼叫(包計時)
238- void doPrecomputeIfEnabled ();
239-
240- void precomputeAllCoordinates ();
241- void precomputeGlobalCoords ();
242- void performSegmentTreeSpecificOptimizations (LiveIntervals &LIS);
243- void validatePostOptimizationState (LiveIntervals &LIS);
244-
245- MachineFunction *MF = nullptr ;
246-
247- // Shortcuts to some useful interface.
248- const TargetInstrInfo *TII = nullptr ;
249-
250- LiveIntervals *LIS = nullptr ;
251- VirtRegMap *VRM = nullptr ;
252- LiveRegMatrix *LRM = nullptr ;
253- MachineRegisterInfo *MRI = nullptr ;
254- const TargetRegisterInfo *TRI = nullptr ;
255-
256- RegisterClassInfo RCI;
257-
258- std::unique_ptr<Spiller> SpillerInstance; // Add this line
259- PQueue Queue;
260- std::optional<ExtraRegInfo> ExtraInfo;
261-
262- std::unique_ptr<RegAllocPriorityAdvisor> PriorityAdvisor;
263-
264- // 工作佇列與去重集合
265- llvm::SmallVector<const LiveInterval*, 64 > CurQueue;
266- llvm::SmallDenseSet<unsigned , 64 > InQ; // 記 vreg id,避免重複排入
267-
268- // Bookkeeping of allocated intervals per physical register (for rebuild).
269- std::vector<std::vector<std::pair<SlotIndex, SlotIndex>>> PhysRegIntervals;
270-
271- // ===------------------------------------------------------------------===//
272- // Lazy segment tree (range add / range max) with coordinate compression
273- // ===------------------------------------------------------------------===//
274- struct SegNode {
275- int maxCover = 0 ; // 節點覆蓋區間內的最大覆蓋次數
276- int lazyAdd = 0 ; // lazy 累加(尚未下推)
277- };
278-
279- // 每個 PhysReg 的座標壓縮點(遞增),點數 m → 段數 m-1
280- std::vector<std::vector<SlotIndex>> PRCoords;
281- std::vector<SlotIndex> GlobalCoords; // 全局座標點(所有 PR 共用)
282-
283- // 每個 PhysReg 的 lazy 線段樹
284- std::vector<std::vector<SegNode>> PRTree;
285-
286- // —— 內部工具 —— //
287- // 確保 PR 的座標包含 [S,E) 的端點;必要時重建樹並回放既有區間
288- // void ensureCoordsAndTree(unsigned PhysReg);
289- void ensureCoordsAndTree (unsigned PhysReg, SlotIndex S, SlotIndex E);
290- void ensureCoordsForPhysReg (unsigned PhysReg);
291- void dumpCoords (unsigned PhysReg) const ;
292- // 把 SlotIndex 映射成座標索引(必須已存在於 PRCoords[PR])
293- unsigned coordIndex (unsigned PhysReg, SlotIndex X) const ;
294-
295- // 線段樹操作
296- void segtreeBuild (unsigned PhysReg);
297- void segtreeUpdate (unsigned PhysReg, unsigned idx, unsigned L, unsigned R,
298- unsigned ql, unsigned qr, int add);
299- int segtreeQueryMax (unsigned PhysReg, unsigned idx, unsigned L, unsigned R,
300- unsigned ql, unsigned qr);
301- int segtreeQueryMaxIter (unsigned PhysReg, unsigned ql, unsigned qr);
302-
303- // 可放檢查(含別名):任一段 maxCover>0 就不可放
304- bool canPlaceOnPhysReg (unsigned PhysReg, const LiveInterval &LI) const ;
305-
306- // 嘗試為給定的虛擬暫存器分配一個物理暫存器
307- // 返回分配的物理暫存器,若失敗則返回0
308- unsigned tryAllocateRegister (LiveInterval &VirtReg);
309-
310- // ===== 分割相關方法群組 =====
311- // 線段樹輔助分割策略
312- MCRegister trySegmentTreeSplit (const LiveInterval &VirtReg,
313- SmallVectorImpl<Register> &NewVRegs);
314-
315- // 基於線段樹分析找到最佳分割點
316- SlotIndex findOptimalSplitPoint (const LiveInterval &VirtReg);
317-
318- // 在指定點執行分割
319- MCRegister performSplitAtPoint (const LiveInterval &VirtReg,
320- SlotIndex SplitPoint,
321- SmallVectorImpl<Register> &NewVRegs);
322-
323- // 檢查物理暫存器是否可用
324- bool isPhysRegAvailable (unsigned PhysReg, const LiveInterval &VirtReg);
325-
326- // 溢出處理:當沒有可用的物理暫存器時,選擇一個虛擬暫存器溢出到內存
327- void spillVirtReg (LiveInterval &VirtReg);
328-
329- // 更新线段树以反映区间的分配
330- void updateSegmentTreeForInterval (const LiveInterval &LI, unsigned PhysReg);
331-
332- // 更新物理寄存器的线段树(分配区间后)
333- void updateSegmentTreeForPhysReg (unsigned PhysReg, SlotIndex Start, SlotIndex End);
334-
335- // 清理失败的虚拟寄存器
336- void cleanupFailedVReg (Register FailedVReg, unsigned Depth,
337- SmallVectorImpl<Register> &SplitRegs);
338-
339- // 找到合適的拆分點
340- SlotIndex findSplitPoint (const LiveInterval &LI);
341- };
342-
343- // 創建SegmentTreeRegisterAllocator實例的函數
13+ // Factory (for -regalloc=segtre). For now it delegates to Greedy (NFC).
34414FunctionPass *createRegAllocSegmentTree ();
345-
34615} // end namespace llvm
34716
348- #endif // LLVM_CODEGEN_REGALLOCSEGMENTTREE_H
17+ #endif
0 commit comments