Skip to content

Commit cf79ef3

Browse files
committed
[RegAlloc] Add scaffold for -regalloc=segmenttree (NFC)
Adds a minimal factory + regalloc registration for . Currently delegates to Greedy allocator. No functional change.
1 parent 5133080 commit cf79ef3

File tree

3 files changed

+16
-1747
lines changed

3 files changed

+16
-1747
lines changed
Lines changed: 5 additions & 336 deletions
Original file line numberDiff line numberDiff line change
@@ -1,348 +1,17 @@
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-
4110
namespace 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).
34414
FunctionPass *createRegAllocSegmentTree();
345-
34615
} // end namespace llvm
34716

348-
#endif // LLVM_CODEGEN_REGALLOCSEGMENTTREE_H
17+
#endif

llvm/lib/CodeGen/CodeGen.cpp

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

0 commit comments

Comments
 (0)