1 | //===- LiveRangeShrink.cpp - Move instructions to shrink live range -------===// |
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 | /// \file |
10 | /// This pass moves instructions close to the definition of its operands to |
11 | /// shrink live range of the def instruction. The code motion is limited within |
12 | /// the basic block. The moved instruction should have 1 def, and more than one |
13 | /// uses, all of which are the only use of the def. |
14 | /// |
15 | ///===---------------------------------------------------------------------===// |
16 | |
17 | #include "llvm/ADT/DenseMap.h" |
18 | #include "llvm/ADT/Statistic.h" |
19 | #include "llvm/ADT/iterator_range.h" |
20 | #include "llvm/CodeGen/MachineBasicBlock.h" |
21 | #include "llvm/CodeGen/MachineFunction.h" |
22 | #include "llvm/CodeGen/MachineFunctionPass.h" |
23 | #include "llvm/CodeGen/MachineInstr.h" |
24 | #include "llvm/CodeGen/MachineOperand.h" |
25 | #include "llvm/CodeGen/MachineRegisterInfo.h" |
26 | #include "llvm/CodeGen/TargetInstrInfo.h" |
27 | #include "llvm/InitializePasses.h" |
28 | #include "llvm/Pass.h" |
29 | #include "llvm/Support/Debug.h" |
30 | #include "llvm/Support/raw_ostream.h" |
31 | #include <iterator> |
32 | #include <utility> |
33 | |
34 | using namespace llvm; |
35 | |
36 | #define DEBUG_TYPE "lrshrink" |
37 | |
38 | STATISTIC(NumInstrsHoistedToShrinkLiveRange, |
39 | "Number of insructions hoisted to shrink live range." ); |
40 | |
41 | namespace { |
42 | |
43 | class LiveRangeShrink : public MachineFunctionPass { |
44 | public: |
45 | static char ID; |
46 | |
47 | LiveRangeShrink() : MachineFunctionPass(ID) { |
48 | initializeLiveRangeShrinkPass(*PassRegistry::getPassRegistry()); |
49 | } |
50 | |
51 | void getAnalysisUsage(AnalysisUsage &AU) const override { |
52 | AU.setPreservesCFG(); |
53 | MachineFunctionPass::getAnalysisUsage(AU); |
54 | } |
55 | |
56 | StringRef getPassName() const override { return "Live Range Shrink" ; } |
57 | |
58 | bool runOnMachineFunction(MachineFunction &MF) override; |
59 | }; |
60 | |
61 | } // end anonymous namespace |
62 | |
63 | char LiveRangeShrink::ID = 0; |
64 | |
65 | char &llvm::LiveRangeShrinkID = LiveRangeShrink::ID; |
66 | |
67 | INITIALIZE_PASS(LiveRangeShrink, "lrshrink" , "Live Range Shrink Pass" , false, |
68 | false) |
69 | |
70 | using InstOrderMap = DenseMap<MachineInstr *, unsigned>; |
71 | |
72 | /// Returns \p New if it's dominated by \p Old, otherwise return \p Old. |
73 | /// \p M maintains a map from instruction to its dominating order that satisfies |
74 | /// M[A] > M[B] guarantees that A is dominated by B. |
75 | /// If \p New is not in \p M, return \p Old. Otherwise if \p Old is null, return |
76 | /// \p New. |
77 | static MachineInstr *FindDominatedInstruction(MachineInstr &New, |
78 | MachineInstr *Old, |
79 | const InstOrderMap &M) { |
80 | auto NewIter = M.find(Val: &New); |
81 | if (NewIter == M.end()) |
82 | return Old; |
83 | if (Old == nullptr) |
84 | return &New; |
85 | unsigned OrderOld = M.find(Val: Old)->second; |
86 | unsigned OrderNew = NewIter->second; |
87 | if (OrderOld != OrderNew) |
88 | return OrderOld < OrderNew ? &New : Old; |
89 | // OrderOld == OrderNew, we need to iterate down from Old to see if it |
90 | // can reach New, if yes, New is dominated by Old. |
91 | for (MachineInstr *I = Old->getNextNode(); M.find(Val: I)->second == OrderNew; |
92 | I = I->getNextNode()) |
93 | if (I == &New) |
94 | return &New; |
95 | return Old; |
96 | } |
97 | |
98 | /// Builds Instruction to its dominating order number map \p M by traversing |
99 | /// from instruction \p Start. |
100 | static void BuildInstOrderMap(MachineBasicBlock::iterator Start, |
101 | InstOrderMap &M) { |
102 | M.clear(); |
103 | unsigned i = 0; |
104 | for (MachineInstr &I : make_range(x: Start, y: Start->getParent()->end())) |
105 | M[&I] = i++; |
106 | } |
107 | |
108 | bool LiveRangeShrink::runOnMachineFunction(MachineFunction &MF) { |
109 | if (skipFunction(F: MF.getFunction())) |
110 | return false; |
111 | |
112 | MachineRegisterInfo &MRI = MF.getRegInfo(); |
113 | const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); |
114 | |
115 | LLVM_DEBUG(dbgs() << "**** Analysing " << MF.getName() << '\n'); |
116 | |
117 | InstOrderMap IOM; |
118 | // Map from register to instruction order (value of IOM) where the |
119 | // register is used last. When moving instructions up, we need to |
120 | // make sure all its defs (including dead def) will not cross its |
121 | // last use when moving up. |
122 | DenseMap<unsigned, std::pair<unsigned, MachineInstr *>> UseMap; |
123 | |
124 | for (MachineBasicBlock &MBB : MF) { |
125 | if (MBB.empty()) |
126 | continue; |
127 | bool SawStore = false; |
128 | BuildInstOrderMap(Start: MBB.begin(), M&: IOM); |
129 | UseMap.clear(); |
130 | |
131 | for (MachineBasicBlock::iterator Next = MBB.begin(); Next != MBB.end();) { |
132 | MachineInstr &MI = *Next; |
133 | ++Next; |
134 | if (MI.isPHI() || MI.isDebugOrPseudoInstr()) |
135 | continue; |
136 | if (MI.mayStore()) |
137 | SawStore = true; |
138 | |
139 | unsigned CurrentOrder = IOM[&MI]; |
140 | unsigned Barrier = 0; |
141 | MachineInstr *BarrierMI = nullptr; |
142 | for (const MachineOperand &MO : MI.operands()) { |
143 | if (!MO.isReg() || MO.isDebug()) |
144 | continue; |
145 | if (MO.isUse()) |
146 | UseMap[MO.getReg()] = std::make_pair(x&: CurrentOrder, y: &MI); |
147 | else if (MO.isDead() && UseMap.count(Val: MO.getReg())) |
148 | // Barrier is the last instruction where MO get used. MI should not |
149 | // be moved above Barrier. |
150 | if (Barrier < UseMap[MO.getReg()].first) { |
151 | Barrier = UseMap[MO.getReg()].first; |
152 | BarrierMI = UseMap[MO.getReg()].second; |
153 | } |
154 | } |
155 | |
156 | if (!MI.isSafeToMove(AA: nullptr, SawStore)) { |
157 | // If MI has side effects, it should become a barrier for code motion. |
158 | // IOM is rebuild from the next instruction to prevent later |
159 | // instructions from being moved before this MI. |
160 | if (MI.hasUnmodeledSideEffects() && !MI.isPseudoProbe() && |
161 | Next != MBB.end()) { |
162 | BuildInstOrderMap(Start: Next, M&: IOM); |
163 | SawStore = false; |
164 | } |
165 | continue; |
166 | } |
167 | |
168 | const MachineOperand *DefMO = nullptr; |
169 | MachineInstr *Insert = nullptr; |
170 | |
171 | // Number of live-ranges that will be shortened. We do not count |
172 | // live-ranges that are defined by a COPY as it could be coalesced later. |
173 | unsigned NumEligibleUse = 0; |
174 | |
175 | for (const MachineOperand &MO : MI.operands()) { |
176 | if (!MO.isReg() || MO.isDead() || MO.isDebug()) |
177 | continue; |
178 | Register Reg = MO.getReg(); |
179 | // Do not move the instruction if it def/uses a physical register, |
180 | // unless it is a constant physical register or a noreg. |
181 | if (!Reg.isVirtual()) { |
182 | if (!Reg || MRI.isConstantPhysReg(PhysReg: Reg)) |
183 | continue; |
184 | Insert = nullptr; |
185 | break; |
186 | } |
187 | if (MO.isDef()) { |
188 | // Do not move if there is more than one def. |
189 | if (DefMO) { |
190 | Insert = nullptr; |
191 | break; |
192 | } |
193 | DefMO = &MO; |
194 | } else if (MRI.hasOneNonDBGUse(RegNo: Reg) && MRI.hasOneDef(RegNo: Reg) && DefMO && |
195 | MRI.getRegClass(Reg: DefMO->getReg()) == |
196 | MRI.getRegClass(Reg: MO.getReg())) { |
197 | // The heuristic does not handle different register classes yet |
198 | // (registers of different sizes, looser/tighter constraints). This |
199 | // is because it needs more accurate model to handle register |
200 | // pressure correctly. |
201 | MachineInstr &DefInstr = *MRI.def_instr_begin(RegNo: Reg); |
202 | if (!TII.isCopyInstr(MI: DefInstr)) |
203 | NumEligibleUse++; |
204 | Insert = FindDominatedInstruction(New&: DefInstr, Old: Insert, M: IOM); |
205 | } else { |
206 | Insert = nullptr; |
207 | break; |
208 | } |
209 | } |
210 | |
211 | // If Barrier equals IOM[I], traverse forward to find if BarrierMI is |
212 | // after Insert, if yes, then we should not hoist. |
213 | for (MachineInstr *I = Insert; I && IOM[I] == Barrier; |
214 | I = I->getNextNode()) |
215 | if (I == BarrierMI) { |
216 | Insert = nullptr; |
217 | break; |
218 | } |
219 | // Move the instruction when # of shrunk live range > 1. |
220 | if (DefMO && Insert && NumEligibleUse > 1 && Barrier <= IOM[Insert]) { |
221 | MachineBasicBlock::iterator I = std::next(x: Insert->getIterator()); |
222 | // Skip all the PHI and debug instructions. |
223 | while (I != MBB.end() && (I->isPHI() || I->isDebugOrPseudoInstr())) |
224 | I = std::next(x: I); |
225 | if (I == MI.getIterator()) |
226 | continue; |
227 | |
228 | // Update the dominator order to be the same as the insertion point. |
229 | // We do this to maintain a non-decreasing order without need to update |
230 | // all instruction orders after the insertion point. |
231 | unsigned NewOrder = IOM[&*I]; |
232 | IOM[&MI] = NewOrder; |
233 | NumInstrsHoistedToShrinkLiveRange++; |
234 | |
235 | // Find MI's debug value following MI. |
236 | MachineBasicBlock::iterator EndIter = std::next(x: MI.getIterator()); |
237 | if (MI.getOperand(i: 0).isReg()) |
238 | for (; EndIter != MBB.end() && EndIter->isDebugValue() && |
239 | EndIter->hasDebugOperandForReg(Reg: MI.getOperand(i: 0).getReg()); |
240 | ++EndIter, ++Next) |
241 | IOM[&*EndIter] = NewOrder; |
242 | MBB.splice(Where: I, Other: &MBB, From: MI.getIterator(), To: EndIter); |
243 | } |
244 | } |
245 | } |
246 | return false; |
247 | } |
248 | |