1 | //===-- RenameIndependentSubregs.cpp - Live Interval Analysis -------------===// |
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 | /// Rename independent subregisters looks for virtual registers with |
10 | /// independently used subregisters and renames them to new virtual registers. |
11 | /// Example: In the following: |
12 | /// %0:sub0<read-undef> = ... |
13 | /// %0:sub1 = ... |
14 | /// use %0:sub0 |
15 | /// %0:sub0 = ... |
16 | /// use %0:sub0 |
17 | /// use %0:sub1 |
18 | /// sub0 and sub1 are never used together, and we have two independent sub0 |
19 | /// definitions. This pass will rename to: |
20 | /// %0:sub0<read-undef> = ... |
21 | /// %1:sub1<read-undef> = ... |
22 | /// use %1:sub1 |
23 | /// %2:sub1<read-undef> = ... |
24 | /// use %2:sub1 |
25 | /// use %0:sub0 |
26 | // |
27 | //===----------------------------------------------------------------------===// |
28 | |
29 | #include "LiveRangeUtils.h" |
30 | #include "PHIEliminationUtils.h" |
31 | #include "llvm/CodeGen/LiveInterval.h" |
32 | #include "llvm/CodeGen/LiveIntervals.h" |
33 | #include "llvm/CodeGen/MachineFunctionPass.h" |
34 | #include "llvm/CodeGen/MachineInstrBuilder.h" |
35 | #include "llvm/CodeGen/MachineRegisterInfo.h" |
36 | #include "llvm/CodeGen/TargetInstrInfo.h" |
37 | #include "llvm/InitializePasses.h" |
38 | #include "llvm/Pass.h" |
39 | |
40 | using namespace llvm; |
41 | |
42 | #define DEBUG_TYPE "rename-independent-subregs" |
43 | |
44 | namespace { |
45 | |
46 | class RenameIndependentSubregs : public MachineFunctionPass { |
47 | public: |
48 | static char ID; |
49 | RenameIndependentSubregs() : MachineFunctionPass(ID) {} |
50 | |
51 | StringRef getPassName() const override { |
52 | return "Rename Disconnected Subregister Components" ; |
53 | } |
54 | |
55 | void getAnalysisUsage(AnalysisUsage &AU) const override { |
56 | AU.setPreservesCFG(); |
57 | AU.addRequired<LiveIntervalsWrapperPass>(); |
58 | AU.addPreserved<LiveIntervalsWrapperPass>(); |
59 | AU.addRequired<SlotIndexesWrapperPass>(); |
60 | AU.addPreserved<SlotIndexesWrapperPass>(); |
61 | MachineFunctionPass::getAnalysisUsage(AU); |
62 | } |
63 | |
64 | bool runOnMachineFunction(MachineFunction &MF) override; |
65 | |
66 | private: |
67 | struct SubRangeInfo { |
68 | ConnectedVNInfoEqClasses ConEQ; |
69 | LiveInterval::SubRange *SR; |
70 | unsigned Index; |
71 | |
72 | SubRangeInfo(LiveIntervals &LIS, LiveInterval::SubRange &SR, |
73 | unsigned Index) |
74 | : ConEQ(LIS), SR(&SR), Index(Index) {} |
75 | }; |
76 | |
77 | /// Split unrelated subregister components and rename them to new vregs. |
78 | bool renameComponents(LiveInterval &LI) const; |
79 | |
80 | /// Build a vector of SubRange infos and a union find set of |
81 | /// equivalence classes. |
82 | /// Returns true if more than 1 equivalence class was found. |
83 | bool findComponents(IntEqClasses &Classes, |
84 | SmallVectorImpl<SubRangeInfo> &SubRangeInfos, |
85 | LiveInterval &LI) const; |
86 | |
87 | /// Distribute the LiveInterval segments into the new LiveIntervals |
88 | /// belonging to their class. |
89 | void distribute(const IntEqClasses &Classes, |
90 | const SmallVectorImpl<SubRangeInfo> &SubRangeInfos, |
91 | const SmallVectorImpl<LiveInterval*> &Intervals) const; |
92 | |
93 | /// Constructs main liverange and add missing undef+dead flags. |
94 | void computeMainRangesFixFlags(const IntEqClasses &Classes, |
95 | const SmallVectorImpl<SubRangeInfo> &SubRangeInfos, |
96 | const SmallVectorImpl<LiveInterval*> &Intervals) const; |
97 | |
98 | /// Rewrite Machine Operands to use the new vreg belonging to their class. |
99 | void rewriteOperands(const IntEqClasses &Classes, |
100 | const SmallVectorImpl<SubRangeInfo> &SubRangeInfos, |
101 | const SmallVectorImpl<LiveInterval*> &Intervals) const; |
102 | |
103 | |
104 | LiveIntervals *LIS = nullptr; |
105 | MachineRegisterInfo *MRI = nullptr; |
106 | const TargetInstrInfo *TII = nullptr; |
107 | }; |
108 | |
109 | } // end anonymous namespace |
110 | |
111 | char RenameIndependentSubregs::ID; |
112 | |
113 | char &llvm::RenameIndependentSubregsID = RenameIndependentSubregs::ID; |
114 | |
115 | INITIALIZE_PASS_BEGIN(RenameIndependentSubregs, DEBUG_TYPE, |
116 | "Rename Independent Subregisters" , false, false) |
117 | INITIALIZE_PASS_DEPENDENCY(SlotIndexesWrapperPass) |
118 | INITIALIZE_PASS_DEPENDENCY(LiveIntervalsWrapperPass) |
119 | INITIALIZE_PASS_END(RenameIndependentSubregs, DEBUG_TYPE, |
120 | "Rename Independent Subregisters" , false, false) |
121 | |
122 | bool RenameIndependentSubregs::renameComponents(LiveInterval &LI) const { |
123 | // Shortcut: We cannot have split components with a single definition. |
124 | if (LI.valnos.size() < 2) |
125 | return false; |
126 | |
127 | SmallVector<SubRangeInfo, 4> SubRangeInfos; |
128 | IntEqClasses Classes; |
129 | if (!findComponents(Classes, SubRangeInfos, LI)) |
130 | return false; |
131 | |
132 | // Create a new VReg for each class. |
133 | Register Reg = LI.reg(); |
134 | const TargetRegisterClass *RegClass = MRI->getRegClass(Reg); |
135 | SmallVector<LiveInterval*, 4> Intervals; |
136 | Intervals.push_back(Elt: &LI); |
137 | LLVM_DEBUG(dbgs() << printReg(Reg) << ": Found " << Classes.getNumClasses() |
138 | << " equivalence classes.\n" ); |
139 | LLVM_DEBUG(dbgs() << printReg(Reg) << ": Splitting into newly created:" ); |
140 | for (unsigned I = 1, NumClasses = Classes.getNumClasses(); I < NumClasses; |
141 | ++I) { |
142 | Register NewVReg = MRI->createVirtualRegister(RegClass); |
143 | LiveInterval &NewLI = LIS->createEmptyInterval(Reg: NewVReg); |
144 | Intervals.push_back(Elt: &NewLI); |
145 | LLVM_DEBUG(dbgs() << ' ' << printReg(NewVReg)); |
146 | } |
147 | LLVM_DEBUG(dbgs() << '\n'); |
148 | |
149 | rewriteOperands(Classes, SubRangeInfos, Intervals); |
150 | distribute(Classes, SubRangeInfos, Intervals); |
151 | computeMainRangesFixFlags(Classes, SubRangeInfos, Intervals); |
152 | return true; |
153 | } |
154 | |
155 | bool RenameIndependentSubregs::findComponents(IntEqClasses &Classes, |
156 | SmallVectorImpl<RenameIndependentSubregs::SubRangeInfo> &SubRangeInfos, |
157 | LiveInterval &LI) const { |
158 | // First step: Create connected components for the VNInfos inside the |
159 | // subranges and count the global number of such components. |
160 | unsigned NumComponents = 0; |
161 | for (LiveInterval::SubRange &SR : LI.subranges()) { |
162 | SubRangeInfos.push_back(Elt: SubRangeInfo(*LIS, SR, NumComponents)); |
163 | ConnectedVNInfoEqClasses &ConEQ = SubRangeInfos.back().ConEQ; |
164 | |
165 | unsigned NumSubComponents = ConEQ.Classify(LR: SR); |
166 | NumComponents += NumSubComponents; |
167 | } |
168 | // Shortcut: With only 1 subrange, the normal separate component tests are |
169 | // enough and we do not need to perform the union-find on the subregister |
170 | // segments. |
171 | if (SubRangeInfos.size() < 2) |
172 | return false; |
173 | |
174 | // Next step: Build union-find structure over all subranges and merge classes |
175 | // across subranges when they are affected by the same MachineOperand. |
176 | const TargetRegisterInfo &TRI = *MRI->getTargetRegisterInfo(); |
177 | Classes.grow(N: NumComponents); |
178 | Register Reg = LI.reg(); |
179 | for (const MachineOperand &MO : MRI->reg_nodbg_operands(Reg)) { |
180 | if (!MO.isDef() && !MO.readsReg()) |
181 | continue; |
182 | unsigned SubRegIdx = MO.getSubReg(); |
183 | LaneBitmask LaneMask = TRI.getSubRegIndexLaneMask(SubIdx: SubRegIdx); |
184 | unsigned MergedID = ~0u; |
185 | for (RenameIndependentSubregs::SubRangeInfo &SRInfo : SubRangeInfos) { |
186 | const LiveInterval::SubRange &SR = *SRInfo.SR; |
187 | if ((SR.LaneMask & LaneMask).none()) |
188 | continue; |
189 | SlotIndex Pos = LIS->getInstructionIndex(Instr: *MO.getParent()); |
190 | Pos = MO.isDef() ? Pos.getRegSlot(EC: MO.isEarlyClobber()) |
191 | : Pos.getBaseIndex(); |
192 | const VNInfo *VNI = SR.getVNInfoAt(Idx: Pos); |
193 | if (VNI == nullptr) |
194 | continue; |
195 | |
196 | // Map to local representant ID. |
197 | unsigned LocalID = SRInfo.ConEQ.getEqClass(VNI); |
198 | // Global ID |
199 | unsigned ID = LocalID + SRInfo.Index; |
200 | // Merge other sets |
201 | MergedID = MergedID == ~0u ? ID : Classes.join(a: MergedID, b: ID); |
202 | } |
203 | } |
204 | |
205 | // Early exit if we ended up with a single equivalence class. |
206 | Classes.compress(); |
207 | unsigned NumClasses = Classes.getNumClasses(); |
208 | return NumClasses > 1; |
209 | } |
210 | |
211 | void RenameIndependentSubregs::rewriteOperands(const IntEqClasses &Classes, |
212 | const SmallVectorImpl<SubRangeInfo> &SubRangeInfos, |
213 | const SmallVectorImpl<LiveInterval*> &Intervals) const { |
214 | const TargetRegisterInfo &TRI = *MRI->getTargetRegisterInfo(); |
215 | unsigned Reg = Intervals[0]->reg(); |
216 | for (MachineRegisterInfo::reg_nodbg_iterator I = MRI->reg_nodbg_begin(RegNo: Reg), |
217 | E = MRI->reg_nodbg_end(); I != E; ) { |
218 | MachineOperand &MO = *I++; |
219 | if (!MO.isDef() && !MO.readsReg()) |
220 | continue; |
221 | |
222 | auto *MI = MO.getParent(); |
223 | SlotIndex Pos = LIS->getInstructionIndex(Instr: *MI); |
224 | Pos = MO.isDef() ? Pos.getRegSlot(EC: MO.isEarlyClobber()) |
225 | : Pos.getBaseIndex(); |
226 | unsigned SubRegIdx = MO.getSubReg(); |
227 | LaneBitmask LaneMask = TRI.getSubRegIndexLaneMask(SubIdx: SubRegIdx); |
228 | |
229 | unsigned ID = ~0u; |
230 | for (const SubRangeInfo &SRInfo : SubRangeInfos) { |
231 | const LiveInterval::SubRange &SR = *SRInfo.SR; |
232 | if ((SR.LaneMask & LaneMask).none()) |
233 | continue; |
234 | const VNInfo *VNI = SR.getVNInfoAt(Idx: Pos); |
235 | if (VNI == nullptr) |
236 | continue; |
237 | |
238 | // Map to local representant ID. |
239 | unsigned LocalID = SRInfo.ConEQ.getEqClass(VNI); |
240 | // Global ID |
241 | ID = Classes[LocalID + SRInfo.Index]; |
242 | break; |
243 | } |
244 | |
245 | unsigned VReg = Intervals[ID]->reg(); |
246 | MO.setReg(VReg); |
247 | |
248 | if (MO.isTied() && Reg != VReg) { |
249 | /// Undef use operands are not tracked in the equivalence class, |
250 | /// but need to be updated if they are tied; take care to only |
251 | /// update the tied operand. |
252 | unsigned OperandNo = MO.getOperandNo(); |
253 | unsigned TiedIdx = MI->findTiedOperandIdx(OpIdx: OperandNo); |
254 | MI->getOperand(i: TiedIdx).setReg(VReg); |
255 | |
256 | // above substitution breaks the iterator, so restart. |
257 | I = MRI->reg_nodbg_begin(RegNo: Reg); |
258 | } |
259 | } |
260 | // TODO: We could attempt to recompute new register classes while visiting |
261 | // the operands: Some of the split register may be fine with less constraint |
262 | // classes than the original vreg. |
263 | } |
264 | |
265 | void RenameIndependentSubregs::distribute(const IntEqClasses &Classes, |
266 | const SmallVectorImpl<SubRangeInfo> &SubRangeInfos, |
267 | const SmallVectorImpl<LiveInterval*> &Intervals) const { |
268 | unsigned NumClasses = Classes.getNumClasses(); |
269 | SmallVector<unsigned, 8> VNIMapping; |
270 | SmallVector<LiveInterval::SubRange*, 8> SubRanges; |
271 | BumpPtrAllocator &Allocator = LIS->getVNInfoAllocator(); |
272 | for (const SubRangeInfo &SRInfo : SubRangeInfos) { |
273 | LiveInterval::SubRange &SR = *SRInfo.SR; |
274 | unsigned NumValNos = SR.valnos.size(); |
275 | VNIMapping.clear(); |
276 | VNIMapping.reserve(N: NumValNos); |
277 | SubRanges.clear(); |
278 | SubRanges.resize(N: NumClasses-1, NV: nullptr); |
279 | for (unsigned I = 0; I < NumValNos; ++I) { |
280 | const VNInfo &VNI = *SR.valnos[I]; |
281 | unsigned LocalID = SRInfo.ConEQ.getEqClass(VNI: &VNI); |
282 | unsigned ID = Classes[LocalID + SRInfo.Index]; |
283 | VNIMapping.push_back(Elt: ID); |
284 | if (ID > 0 && SubRanges[ID-1] == nullptr) |
285 | SubRanges[ID-1] = Intervals[ID]->createSubRange(Allocator, LaneMask: SR.LaneMask); |
286 | } |
287 | DistributeRange(LR&: SR, SplitLRs: SubRanges.data(), VNIClasses: VNIMapping); |
288 | } |
289 | } |
290 | |
291 | static bool subRangeLiveAt(const LiveInterval &LI, SlotIndex Pos) { |
292 | for (const LiveInterval::SubRange &SR : LI.subranges()) { |
293 | if (SR.liveAt(index: Pos)) |
294 | return true; |
295 | } |
296 | return false; |
297 | } |
298 | |
299 | void RenameIndependentSubregs::computeMainRangesFixFlags( |
300 | const IntEqClasses &Classes, |
301 | const SmallVectorImpl<SubRangeInfo> &SubRangeInfos, |
302 | const SmallVectorImpl<LiveInterval*> &Intervals) const { |
303 | BumpPtrAllocator &Allocator = LIS->getVNInfoAllocator(); |
304 | const SlotIndexes &Indexes = *LIS->getSlotIndexes(); |
305 | for (size_t I = 0, E = Intervals.size(); I < E; ++I) { |
306 | LiveInterval &LI = *Intervals[I]; |
307 | Register Reg = LI.reg(); |
308 | |
309 | LI.removeEmptySubRanges(); |
310 | |
311 | // There must be a def (or live-in) before every use. Splitting vregs may |
312 | // violate this principle as the splitted vreg may not have a definition on |
313 | // every path. Fix this by creating IMPLICIT_DEF instruction as necessary. |
314 | for (const LiveInterval::SubRange &SR : LI.subranges()) { |
315 | // Search for "PHI" value numbers in the subranges. We must find a live |
316 | // value in each predecessor block, add an IMPLICIT_DEF where it is |
317 | // missing. |
318 | for (unsigned I = 0; I < SR.valnos.size(); ++I) { |
319 | const VNInfo &VNI = *SR.valnos[I]; |
320 | if (VNI.isUnused() || !VNI.isPHIDef()) |
321 | continue; |
322 | |
323 | SlotIndex Def = VNI.def; |
324 | MachineBasicBlock &MBB = *Indexes.getMBBFromIndex(index: Def); |
325 | for (MachineBasicBlock *PredMBB : MBB.predecessors()) { |
326 | SlotIndex PredEnd = Indexes.getMBBEndIdx(mbb: PredMBB); |
327 | if (subRangeLiveAt(LI, Pos: PredEnd.getPrevSlot())) |
328 | continue; |
329 | |
330 | MachineBasicBlock::iterator InsertPos = |
331 | llvm::findPHICopyInsertPoint(MBB: PredMBB, SuccMBB: &MBB, SrcReg: Reg); |
332 | const MCInstrDesc &MCDesc = TII->get(Opcode: TargetOpcode::IMPLICIT_DEF); |
333 | MachineInstrBuilder ImpDef = BuildMI(BB&: *PredMBB, I: InsertPos, |
334 | MIMD: DebugLoc(), MCID: MCDesc, DestReg: Reg); |
335 | SlotIndex DefIdx = LIS->InsertMachineInstrInMaps(MI&: *ImpDef); |
336 | SlotIndex RegDefIdx = DefIdx.getRegSlot(); |
337 | LaneBitmask Mask = MRI->getMaxLaneMaskForVReg(Reg); |
338 | for (LiveInterval::SubRange &SR : LI.subranges()) { |
339 | Mask = Mask & ~SR.LaneMask; |
340 | VNInfo *SRVNI = SR.getNextValue(Def: RegDefIdx, VNInfoAllocator&: Allocator); |
341 | SR.addSegment(S: LiveRange::Segment(RegDefIdx, PredEnd, SRVNI)); |
342 | } |
343 | |
344 | if (!Mask.none()) { |
345 | LiveInterval::SubRange *SR = LI.createSubRange(Allocator, LaneMask: Mask); |
346 | SR->createDeadDef(Def: RegDefIdx, VNIAlloc&: Allocator); |
347 | } |
348 | } |
349 | } |
350 | } |
351 | |
352 | for (MachineOperand &MO : MRI->reg_nodbg_operands(Reg)) { |
353 | if (!MO.isDef()) |
354 | continue; |
355 | unsigned SubRegIdx = MO.getSubReg(); |
356 | if (SubRegIdx == 0) |
357 | continue; |
358 | // After assigning the new vreg we may not have any other sublanes living |
359 | // in and out of the instruction anymore. We need to add new dead and |
360 | // undef flags in these cases. |
361 | if (!MO.isUndef()) { |
362 | SlotIndex Pos = LIS->getInstructionIndex(Instr: *MO.getParent()); |
363 | if (!subRangeLiveAt(LI, Pos)) |
364 | MO.setIsUndef(); |
365 | } |
366 | if (!MO.isDead()) { |
367 | SlotIndex Pos = LIS->getInstructionIndex(Instr: *MO.getParent()).getDeadSlot(); |
368 | if (!subRangeLiveAt(LI, Pos)) |
369 | MO.setIsDead(); |
370 | } |
371 | } |
372 | |
373 | if (I == 0) |
374 | LI.clear(); |
375 | LIS->constructMainRangeFromSubranges(LI); |
376 | // A def of a subregister may be a use of other register lanes. Replacing |
377 | // such a def with a def of a different register will eliminate the use, |
378 | // and may cause the recorded live range to be larger than the actual |
379 | // liveness in the program IR. |
380 | LIS->shrinkToUses(li: &LI); |
381 | } |
382 | } |
383 | |
384 | bool RenameIndependentSubregs::runOnMachineFunction(MachineFunction &MF) { |
385 | // Skip renaming if liveness of subregister is not tracked. |
386 | MRI = &MF.getRegInfo(); |
387 | if (!MRI->subRegLivenessEnabled()) |
388 | return false; |
389 | |
390 | LLVM_DEBUG(dbgs() << "Renaming independent subregister live ranges in " |
391 | << MF.getName() << '\n'); |
392 | |
393 | LIS = &getAnalysis<LiveIntervalsWrapperPass>().getLIS(); |
394 | TII = MF.getSubtarget().getInstrInfo(); |
395 | |
396 | // Iterate over all vregs. Note that we query getNumVirtRegs() the newly |
397 | // created vregs end up with higher numbers but do not need to be visited as |
398 | // there can't be any further splitting. |
399 | bool Changed = false; |
400 | for (size_t I = 0, E = MRI->getNumVirtRegs(); I < E; ++I) { |
401 | Register Reg = Register::index2VirtReg(Index: I); |
402 | if (!LIS->hasInterval(Reg)) |
403 | continue; |
404 | LiveInterval &LI = LIS->getInterval(Reg); |
405 | if (!LI.hasSubRanges()) |
406 | continue; |
407 | |
408 | Changed |= renameComponents(LI); |
409 | } |
410 | |
411 | return Changed; |
412 | } |
413 | |