clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name CriticalAntiDepBreaker.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/gnu/usr.bin/clang/libLLVM/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Analysis -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ASMParser -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/BinaryFormat -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Bitcode -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Bitcode -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Bitstream -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /include/llvm/CodeGen -I /include/llvm/CodeGen/PBQP -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/IR -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/IR -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/Coroutines -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ProfileData/Coverage -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo/CodeView -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo/DWARF -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo/MSF -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo/PDB -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Demangle -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ExecutionEngine -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ExecutionEngine/JITLink -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ExecutionEngine/Orc -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Frontend -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Frontend/OpenACC -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Frontend -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Frontend/OpenMP -I /include/llvm/CodeGen/GlobalISel -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/IRReader -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/InstCombine -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/Transforms/InstCombine -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/LTO -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Linker -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/MC -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/MC/MCParser -I /include/llvm/CodeGen/MIRParser -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Object -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Option -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Passes -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ProfileData -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/Scalar -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ADT -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Support -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo/Symbolize -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Target -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/Utils -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/Vectorize -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/IPO -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include -I /usr/src/gnu/usr.bin/clang/libLLVM/../include -I /usr/src/gnu/usr.bin/clang/libLLVM/obj -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include -D NDEBUG -D __STDC_LIMIT_MACROS -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D LLVM_PREFIX="/usr" -internal-isystem /usr/include/c++/v1 -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-comment -std=c++14 -fdeprecated-macro -fdebug-compilation-dir=/usr/src/gnu/usr.bin/clang/libLLVM/obj -ferror-limit 19 -fvisibility-inlines-hidden -fwrapv -stack-protector 2 -fno-rtti -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c++ /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/CodeGen/CriticalAntiDepBreaker.cpp
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | #include "CriticalAntiDepBreaker.h" |
16 | #include "llvm/ADT/ArrayRef.h" |
17 | #include "llvm/ADT/DenseMap.h" |
18 | #include "llvm/ADT/SmallVector.h" |
19 | #include "llvm/CodeGen/MachineBasicBlock.h" |
20 | #include "llvm/CodeGen/MachineFrameInfo.h" |
21 | #include "llvm/CodeGen/MachineFunction.h" |
22 | #include "llvm/CodeGen/MachineInstr.h" |
23 | #include "llvm/CodeGen/MachineOperand.h" |
24 | #include "llvm/CodeGen/MachineRegisterInfo.h" |
25 | #include "llvm/CodeGen/RegisterClassInfo.h" |
26 | #include "llvm/CodeGen/ScheduleDAG.h" |
27 | #include "llvm/CodeGen/TargetInstrInfo.h" |
28 | #include "llvm/CodeGen/TargetRegisterInfo.h" |
29 | #include "llvm/CodeGen/TargetSubtargetInfo.h" |
30 | #include "llvm/MC/MCInstrDesc.h" |
31 | #include "llvm/MC/MCRegisterInfo.h" |
32 | #include "llvm/Support/Debug.h" |
33 | #include "llvm/Support/raw_ostream.h" |
34 | #include <cassert> |
35 | #include <utility> |
36 | |
37 | using namespace llvm; |
38 | |
39 | #define DEBUG_TYPE "post-RA-sched" |
40 | |
41 | CriticalAntiDepBreaker::CriticalAntiDepBreaker(MachineFunction &MFi, |
42 | const RegisterClassInfo &RCI) |
43 | : AntiDepBreaker(), MF(MFi), MRI(MF.getRegInfo()), |
44 | TII(MF.getSubtarget().getInstrInfo()), |
45 | TRI(MF.getSubtarget().getRegisterInfo()), RegClassInfo(RCI), |
46 | Classes(TRI->getNumRegs(), nullptr), KillIndices(TRI->getNumRegs(), 0), |
47 | DefIndices(TRI->getNumRegs(), 0), KeepRegs(TRI->getNumRegs(), false) {} |
48 | |
49 | CriticalAntiDepBreaker::~CriticalAntiDepBreaker() = default; |
50 | |
51 | void CriticalAntiDepBreaker::StartBlock(MachineBasicBlock *BB) { |
52 | const unsigned BBSize = BB->size(); |
53 | for (unsigned i = 0, e = TRI->getNumRegs(); i != e; ++i) { |
54 | |
55 | Classes[i] = nullptr; |
56 | |
57 | |
58 | KillIndices[i] = ~0u; |
59 | DefIndices[i] = BBSize; |
60 | } |
61 | |
62 | |
63 | KeepRegs.reset(); |
64 | |
65 | bool IsReturnBlock = BB->isReturnBlock(); |
66 | |
67 | |
68 | for (const MachineBasicBlock *Succ : BB->successors()) |
69 | for (const auto &LI : Succ->liveins()) { |
70 | for (MCRegAliasIterator AI(LI.PhysReg, TRI, true); AI.isValid(); ++AI) { |
71 | unsigned Reg = *AI; |
72 | Classes[Reg] = reinterpret_cast<TargetRegisterClass *>(-1); |
73 | KillIndices[Reg] = BBSize; |
74 | DefIndices[Reg] = ~0u; |
75 | } |
76 | } |
77 | |
78 | |
79 | |
80 | |
81 | const MachineFrameInfo &MFI = MF.getFrameInfo(); |
82 | BitVector Pristine = MFI.getPristineRegs(MF); |
83 | for (const MCPhysReg *I = MF.getRegInfo().getCalleeSavedRegs(); *I; |
84 | ++I) { |
85 | unsigned Reg = *I; |
86 | if (!IsReturnBlock && !Pristine.test(Reg)) |
87 | continue; |
88 | for (MCRegAliasIterator AI(*I, TRI, true); AI.isValid(); ++AI) { |
89 | unsigned Reg = *AI; |
90 | Classes[Reg] = reinterpret_cast<TargetRegisterClass *>(-1); |
91 | KillIndices[Reg] = BBSize; |
92 | DefIndices[Reg] = ~0u; |
93 | } |
94 | } |
95 | } |
96 | |
97 | void CriticalAntiDepBreaker::FinishBlock() { |
98 | RegRefs.clear(); |
99 | KeepRegs.reset(); |
100 | } |
101 | |
102 | void CriticalAntiDepBreaker::Observe(MachineInstr &MI, unsigned Count, |
103 | unsigned InsertPosIndex) { |
104 | |
105 | |
106 | |
107 | |
108 | |
109 | |
110 | |
111 | if (MI.isDebugInstr() || MI.isKill()) |
112 | return; |
113 | assert(Count < InsertPosIndex && "Instruction index out of expected range!"); |
114 | |
115 | for (unsigned Reg = 0; Reg != TRI->getNumRegs(); ++Reg) { |
116 | if (KillIndices[Reg] != ~0u) { |
117 | |
118 | |
119 | |
120 | Classes[Reg] = reinterpret_cast<TargetRegisterClass *>(-1); |
121 | KillIndices[Reg] = Count; |
122 | } else if (DefIndices[Reg] < InsertPosIndex && DefIndices[Reg] >= Count) { |
123 | |
124 | |
125 | |
126 | |
127 | Classes[Reg] = reinterpret_cast<TargetRegisterClass *>(-1); |
128 | |
129 | |
130 | |
131 | DefIndices[Reg] = InsertPosIndex; |
132 | } |
133 | } |
134 | |
135 | PrescanInstruction(MI); |
136 | ScanInstruction(MI, Count); |
137 | } |
138 | |
139 | |
140 | |
141 | static const SDep *CriticalPathStep(const SUnit *SU) { |
142 | const SDep *Next = nullptr; |
143 | unsigned NextDepth = 0; |
144 | |
145 | for (const SDep &P : SU->Preds) { |
146 | const SUnit *PredSU = P.getSUnit(); |
147 | unsigned PredLatency = P.getLatency(); |
148 | unsigned PredTotalLatency = PredSU->getDepth() + PredLatency; |
149 | |
150 | |
151 | if (NextDepth < PredTotalLatency || |
152 | (NextDepth == PredTotalLatency && P.getKind() == SDep::Anti)) { |
153 | NextDepth = PredTotalLatency; |
154 | Next = &P; |
155 | } |
156 | } |
157 | return Next; |
158 | } |
159 | |
160 | void CriticalAntiDepBreaker::PrescanInstruction(MachineInstr &MI) { |
161 | |
162 | |
163 | |
164 | |
165 | |
166 | |
167 | |
168 | |
169 | |
170 | |
171 | |
172 | |
173 | |
174 | |
175 | |
176 | |
177 | bool Special = |
178 | MI.isCall() || MI.hasExtraSrcRegAllocReq() || TII->isPredicated(MI); |
179 | |
180 | |
181 | |
182 | for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { |
183 | MachineOperand &MO = MI.getOperand(i); |
184 | if (!MO.isReg()) continue; |
185 | Register Reg = MO.getReg(); |
186 | if (Reg == 0) continue; |
187 | const TargetRegisterClass *NewRC = nullptr; |
188 | |
189 | if (i < MI.getDesc().getNumOperands()) |
190 | NewRC = TII->getRegClass(MI.getDesc(), i, TRI, MF); |
191 | |
192 | |
193 | |
194 | if (!Classes[Reg] && NewRC) |
195 | Classes[Reg] = NewRC; |
196 | else if (!NewRC || Classes[Reg] != NewRC) |
197 | Classes[Reg] = reinterpret_cast<TargetRegisterClass *>(-1); |
198 | |
199 | |
200 | for (MCRegAliasIterator AI(Reg, TRI, false); AI.isValid(); ++AI) { |
201 | |
202 | |
203 | |
204 | unsigned AliasReg = *AI; |
205 | if (Classes[AliasReg]) { |
206 | Classes[AliasReg] = reinterpret_cast<TargetRegisterClass *>(-1); |
207 | Classes[Reg] = reinterpret_cast<TargetRegisterClass *>(-1); |
208 | } |
209 | } |
210 | |
211 | |
212 | if (Classes[Reg] != reinterpret_cast<TargetRegisterClass *>(-1)) |
213 | RegRefs.insert(std::make_pair(Reg, &MO)); |
214 | |
215 | |
216 | |
217 | |
218 | |
219 | |
220 | |
221 | |
222 | |
223 | |
224 | |
225 | if (MI.isRegTiedToUseOperand(i) && |
226 | Classes[Reg] == reinterpret_cast<TargetRegisterClass *>(-1)) { |
227 | for (MCSubRegIterator SubRegs(Reg, TRI, true); |
228 | SubRegs.isValid(); ++SubRegs) { |
229 | KeepRegs.set(*SubRegs); |
230 | } |
231 | for (MCSuperRegIterator SuperRegs(Reg, TRI); |
232 | SuperRegs.isValid(); ++SuperRegs) { |
233 | KeepRegs.set(*SuperRegs); |
234 | } |
235 | } |
236 | |
237 | if (MO.isUse() && Special) { |
238 | if (!KeepRegs.test(Reg)) { |
239 | for (MCSubRegIterator SubRegs(Reg, TRI, true); |
240 | SubRegs.isValid(); ++SubRegs) |
241 | KeepRegs.set(*SubRegs); |
242 | } |
243 | } |
244 | } |
245 | } |
246 | |
247 | void CriticalAntiDepBreaker::ScanInstruction(MachineInstr &MI, unsigned Count) { |
248 | |
249 | |
250 | |
251 | assert(!MI.isKill() && "Attempting to scan a kill instruction"); |
252 | |
253 | if (!TII->isPredicated(MI)) { |
| 20 | | Assuming the condition is true | |
|
| |
254 | |
255 | |
256 | for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { |
| 22 | | Loop condition is true. Entering loop body | |
|
257 | MachineOperand &MO = MI.getOperand(i); |
258 | |
259 | if (MO.isRegMask()) { |
| |
260 | auto ClobbersPhysRegAndSubRegs = [&](unsigned PhysReg) { |
261 | for (MCSubRegIterator SRI(PhysReg, TRI, true); SRI.isValid(); ++SRI) |
262 | if (!MO.clobbersPhysReg(*SRI)) |
263 | return false; |
264 | |
265 | return true; |
266 | }; |
267 | |
268 | for (unsigned i = 0, e = TRI->getNumRegs(); i != e; ++i) { |
| 24 | | Assuming 'i' is not equal to 'e' | |
|
| 25 | | Loop condition is true. Entering loop body | |
|
| 28 | | Assuming 'i' is equal to 'e' | |
|
| 29 | | Loop condition is false. Execution continues on line 279 | |
|
269 | if (ClobbersPhysRegAndSubRegs(i)) { |
| 26 | | Assuming the condition is false | |
|
| |
270 | DefIndices[i] = Count; |
271 | KillIndices[i] = ~0u; |
272 | KeepRegs.reset(i); |
273 | Classes[i] = nullptr; |
274 | RegRefs.erase(i); |
275 | } |
276 | } |
277 | } |
278 | |
279 | if (!MO.isReg()) continue; |
| |
280 | Register Reg = MO.getReg(); |
281 | if (Reg == 0) continue; |
| |
282 | if (!MO.isDef()) continue; |
| 32 | | Assuming the condition is false | |
|
| |
283 | |
284 | |
285 | if (MI.isRegTiedToUseOperand(i)) |
| |
286 | continue; |
287 | |
288 | |
289 | |
290 | bool Keep = KeepRegs.test(Reg); |
291 | |
292 | |
293 | |
294 | for (MCSubRegIterator SRI(Reg, TRI, true); SRI.isValid(); ++SRI) { |
| 35 | | Loop condition is false. Execution continues on line 304 | |
|
295 | unsigned SubregReg = *SRI; |
296 | DefIndices[SubregReg] = Count; |
297 | KillIndices[SubregReg] = ~0u; |
298 | Classes[SubregReg] = nullptr; |
299 | RegRefs.erase(SubregReg); |
300 | if (!Keep) |
301 | KeepRegs.reset(SubregReg); |
302 | } |
303 | |
304 | for (MCSuperRegIterator SR(Reg, TRI); SR.isValid(); ++SR) |
| 36 | | Calling constructor for 'MCSuperRegIterator' | |
|
305 | Classes[*SR] = reinterpret_cast<TargetRegisterClass *>(-1); |
306 | } |
307 | } |
308 | for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { |
309 | MachineOperand &MO = MI.getOperand(i); |
310 | if (!MO.isReg()) continue; |
311 | Register Reg = MO.getReg(); |
312 | if (Reg == 0) continue; |
313 | if (!MO.isUse()) continue; |
314 | |
315 | const TargetRegisterClass *NewRC = nullptr; |
316 | if (i < MI.getDesc().getNumOperands()) |
317 | NewRC = TII->getRegClass(MI.getDesc(), i, TRI, MF); |
318 | |
319 | |
320 | |
321 | if (!Classes[Reg] && NewRC) |
322 | Classes[Reg] = NewRC; |
323 | else if (!NewRC || Classes[Reg] != NewRC) |
324 | Classes[Reg] = reinterpret_cast<TargetRegisterClass *>(-1); |
325 | |
326 | RegRefs.insert(std::make_pair(Reg, &MO)); |
327 | |
328 | |
329 | |
330 | for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI) { |
331 | unsigned AliasReg = *AI; |
332 | if (KillIndices[AliasReg] == ~0u) { |
333 | KillIndices[AliasReg] = Count; |
334 | DefIndices[AliasReg] = ~0u; |
335 | } |
336 | } |
337 | } |
338 | } |
339 | |
340 | |
341 | |
342 | |
343 | |
344 | |
345 | |
346 | |
347 | |
348 | |
349 | |
350 | |
351 | bool |
352 | CriticalAntiDepBreaker::isNewRegClobberedByRefs(RegRefIter RegRefBegin, |
353 | RegRefIter RegRefEnd, |
354 | unsigned NewReg) { |
355 | for (RegRefIter I = RegRefBegin; I != RegRefEnd; ++I ) { |
356 | MachineOperand *RefOper = I->second; |
357 | |
358 | |
359 | |
360 | |
361 | if (RefOper->isDef() && RefOper->isEarlyClobber()) |
362 | return true; |
363 | |
364 | |
365 | MachineInstr *MI = RefOper->getParent(); |
366 | for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { |
367 | const MachineOperand &CheckOper = MI->getOperand(i); |
368 | |
369 | if (CheckOper.isRegMask() && CheckOper.clobbersPhysReg(NewReg)) |
370 | return true; |
371 | |
372 | if (!CheckOper.isReg() || !CheckOper.isDef() || |
373 | CheckOper.getReg() != NewReg) |
374 | continue; |
375 | |
376 | |
377 | |
378 | if (RefOper->isDef()) |
379 | return true; |
380 | |
381 | |
382 | |
383 | if (CheckOper.isEarlyClobber()) |
384 | return true; |
385 | |
386 | |
387 | |
388 | if (MI->isInlineAsm()) |
389 | return true; |
390 | } |
391 | } |
392 | return false; |
393 | } |
394 | |
395 | unsigned CriticalAntiDepBreaker:: |
396 | findSuitableFreeRegister(RegRefIter RegRefBegin, |
397 | RegRefIter RegRefEnd, |
398 | unsigned AntiDepReg, |
399 | unsigned LastNewReg, |
400 | const TargetRegisterClass *RC, |
401 | SmallVectorImpl<unsigned> &Forbid) { |
402 | ArrayRef<MCPhysReg> Order = RegClassInfo.getOrder(RC); |
403 | for (unsigned i = 0; i != Order.size(); ++i) { |
404 | unsigned NewReg = Order[i]; |
405 | |
406 | if (NewReg == AntiDepReg) continue; |
407 | |
408 | |
409 | |
410 | if (NewReg == LastNewReg) continue; |
411 | |
412 | |
413 | |
414 | if (isNewRegClobberedByRefs(RegRefBegin, RegRefEnd, NewReg)) continue; |
415 | |
416 | |
417 | assert(((KillIndices[AntiDepReg] == ~0u) != (DefIndices[AntiDepReg] == ~0u)) |
418 | && "Kill and Def maps aren't consistent for AntiDepReg!"); |
419 | assert(((KillIndices[NewReg] == ~0u) != (DefIndices[NewReg] == ~0u)) |
420 | && "Kill and Def maps aren't consistent for NewReg!"); |
421 | if (KillIndices[NewReg] != ~0u || |
422 | Classes[NewReg] == reinterpret_cast<TargetRegisterClass *>(-1) || |
423 | KillIndices[AntiDepReg] > DefIndices[NewReg]) |
424 | continue; |
425 | |
426 | bool Forbidden = false; |
427 | for (unsigned R : Forbid) |
428 | if (TRI->regsOverlap(NewReg, R)) { |
429 | Forbidden = true; |
430 | break; |
431 | } |
432 | if (Forbidden) continue; |
433 | return NewReg; |
434 | } |
435 | |
436 | |
437 | return 0; |
438 | } |
439 | |
440 | unsigned CriticalAntiDepBreaker:: |
441 | BreakAntiDependencies(const std::vector<SUnit> &SUnits, |
442 | MachineBasicBlock::iterator Begin, |
443 | MachineBasicBlock::iterator End, |
444 | unsigned InsertPosIndex, |
445 | DbgValueVector &DbgValues) { |
446 | |
447 | |
448 | if (SUnits.empty()) return 0; |
| 1 | Assuming the condition is false | |
|
| |
449 | |
450 | |
451 | |
452 | |
453 | |
454 | DenseMap<MachineInstr *, const SUnit *> MISUnitMap; |
455 | |
456 | |
457 | const SUnit *Max = nullptr; |
458 | for (unsigned i = 0, e = SUnits.size(); i != e; ++i) { |
| 3 | | Assuming 'i' is not equal to 'e' | |
|
| 4 | | Loop condition is true. Entering loop body | |
|
| 5 | | Assuming 'i' is equal to 'e' | |
|
| 6 | | Loop condition is false. Execution continues on line 464 | |
|
459 | const SUnit *SU = &SUnits[i]; |
460 | MISUnitMap[SU->getInstr()] = SU; |
461 | if (!Max || SU->getDepth() + SU->Latency > Max->getDepth() + Max->Latency) |
462 | Max = SU; |
463 | } |
464 | assert(Max && "Failed to find bottom of the critical path"); |
465 | |
466 | #ifndef NDEBUG |
467 | { |
468 | LLVM_DEBUG(dbgs() << "Critical path has total latency " |
469 | << (Max->getDepth() + Max->Latency) << "\n"); |
470 | LLVM_DEBUG(dbgs() << "Available regs:"); |
471 | for (unsigned Reg = 0; Reg < TRI->getNumRegs(); ++Reg) { |
472 | if (KillIndices[Reg] == ~0u) |
473 | LLVM_DEBUG(dbgs() << " " << printReg(Reg, TRI)); |
474 | } |
475 | LLVM_DEBUG(dbgs() << '\n'); |
476 | } |
477 | #endif |
478 | |
479 | |
480 | |
481 | const SUnit *CriticalPathSU = Max; |
482 | MachineInstr *CriticalPathMI = CriticalPathSU->getInstr(); |
483 | |
484 | |
485 | |
486 | |
487 | |
488 | |
489 | |
490 | |
491 | |
492 | |
493 | |
494 | |
495 | |
496 | |
497 | |
498 | |
499 | |
500 | |
501 | |
502 | |
503 | |
504 | |
505 | |
506 | |
507 | |
508 | |
509 | |
510 | |
511 | |
512 | |
513 | |
514 | |
515 | |
516 | |
517 | |
518 | |
519 | |
520 | |
521 | |
522 | |
523 | |
524 | |
525 | std::vector<unsigned> LastNewReg(TRI->getNumRegs(), 0); |
526 | |
527 | |
528 | |
529 | |
530 | unsigned Broken = 0; |
531 | unsigned Count = InsertPosIndex - 1; |
532 | for (MachineBasicBlock::iterator I = End, E = Begin; I != E; --Count) { |
| 7 | | Loop condition is true. Entering loop body | |
|
533 | MachineInstr &MI = *--I; |
534 | |
535 | |
536 | |
537 | |
538 | |
539 | |
540 | |
541 | if (MI.isDebugInstr() || MI.isKill()) |
| |
542 | continue; |
543 | |
544 | |
545 | |
546 | |
547 | |
548 | |
549 | |
550 | |
551 | |
552 | |
553 | |
554 | |
555 | |
556 | |
557 | unsigned AntiDepReg = 0; |
558 | if (&MI == CriticalPathMI) { |
| 9 | | Assuming the condition is false | |
|
| |
559 | if (const SDep *Edge = CriticalPathStep(CriticalPathSU)) { |
560 | const SUnit *NextSU = Edge->getSUnit(); |
561 | |
562 | |
563 | if (Edge->getKind() == SDep::Anti) { |
564 | AntiDepReg = Edge->getReg(); |
565 | assert(AntiDepReg != 0 && "Anti-dependence on reg0?"); |
566 | if (!MRI.isAllocatable(AntiDepReg)) |
567 | |
568 | AntiDepReg = 0; |
569 | else if (KeepRegs.test(AntiDepReg)) |
570 | |
571 | |
572 | AntiDepReg = 0; |
573 | else { |
574 | |
575 | |
576 | |
577 | |
578 | |
579 | |
580 | |
581 | |
582 | for (const SDep &P : CriticalPathSU->Preds) |
583 | if (P.getSUnit() == NextSU |
584 | ? (P.getKind() != SDep::Anti || P.getReg() != AntiDepReg) |
585 | : (P.getKind() == SDep::Data && |
586 | P.getReg() == AntiDepReg)) { |
587 | AntiDepReg = 0; |
588 | break; |
589 | } |
590 | } |
591 | } |
592 | CriticalPathSU = NextSU; |
593 | CriticalPathMI = CriticalPathSU->getInstr(); |
594 | } else { |
595 | |
596 | CriticalPathSU = nullptr; |
597 | CriticalPathMI = nullptr; |
598 | } |
599 | } |
600 | |
601 | PrescanInstruction(MI); |
602 | |
603 | SmallVector<unsigned, 2> ForbidRegs; |
604 | |
605 | |
606 | |
607 | |
608 | if (MI.isCall() || MI.hasExtraDefRegAllocReq() || TII->isPredicated(MI)) |
| 11 | | Assuming the condition is false | |
|
| 12 | | Assuming the condition is false | |
|
| 13 | | Assuming the condition is false | |
|
| |
609 | |
610 | |
611 | AntiDepReg = 0; |
612 | else if (AntiDepReg) { |
| |
613 | |
614 | |
615 | |
616 | |
617 | for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { |
618 | MachineOperand &MO = MI.getOperand(i); |
619 | if (!MO.isReg()) continue; |
620 | Register Reg = MO.getReg(); |
621 | if (Reg == 0) continue; |
622 | if (MO.isUse() && TRI->regsOverlap(AntiDepReg, Reg)) { |
623 | AntiDepReg = 0; |
624 | break; |
625 | } |
626 | if (MO.isDef() && Reg != AntiDepReg) |
627 | ForbidRegs.push_back(Reg); |
628 | } |
629 | } |
630 | |
631 | |
632 | |
633 | const TargetRegisterClass *RC = AntiDepReg != 0 ? Classes[AntiDepReg] |
| |
634 | : nullptr; |
635 | assert((AntiDepReg == 0 || RC != nullptr) && |
636 | "Register should be live if it's causing an anti-dependence!"); |
637 | if (RC == reinterpret_cast<TargetRegisterClass *>(-1)) |
| |
638 | AntiDepReg = 0; |
639 | |
640 | |
641 | |
642 | |
643 | |
644 | if (AntiDepReg != 0) { |
| |
645 | std::pair<std::multimap<unsigned, MachineOperand *>::iterator, |
646 | std::multimap<unsigned, MachineOperand *>::iterator> |
647 | Range = RegRefs.equal_range(AntiDepReg); |
648 | if (unsigned NewReg = findSuitableFreeRegister(Range.first, Range.second, |
649 | AntiDepReg, |
650 | LastNewReg[AntiDepReg], |
651 | RC, ForbidRegs)) { |
652 | LLVM_DEBUG(dbgs() << "Breaking anti-dependence edge on " |
653 | << printReg(AntiDepReg, TRI) << " with " |
654 | << RegRefs.count(AntiDepReg) << " references" |
655 | << " using " << printReg(NewReg, TRI) << "!\n"); |
656 | |
657 | |
658 | |
659 | for (std::multimap<unsigned, MachineOperand *>::iterator |
660 | Q = Range.first, QE = Range.second; Q != QE; ++Q) { |
661 | Q->second->setReg(NewReg); |
662 | |
663 | |
664 | |
665 | const SUnit *SU = MISUnitMap[Q->second->getParent()]; |
666 | if (!SU) continue; |
667 | UpdateDbgValues(DbgValues, Q->second->getParent(), |
668 | AntiDepReg, NewReg); |
669 | } |
670 | |
671 | |
672 | |
673 | |
674 | Classes[NewReg] = Classes[AntiDepReg]; |
675 | DefIndices[NewReg] = DefIndices[AntiDepReg]; |
676 | KillIndices[NewReg] = KillIndices[AntiDepReg]; |
677 | assert(((KillIndices[NewReg] == ~0u) != |
678 | (DefIndices[NewReg] == ~0u)) && |
679 | "Kill and Def maps aren't consistent for NewReg!"); |
680 | |
681 | Classes[AntiDepReg] = nullptr; |
682 | DefIndices[AntiDepReg] = KillIndices[AntiDepReg]; |
683 | KillIndices[AntiDepReg] = ~0u; |
684 | assert(((KillIndices[AntiDepReg] == ~0u) != |
685 | (DefIndices[AntiDepReg] == ~0u)) && |
686 | "Kill and Def maps aren't consistent for AntiDepReg!"); |
687 | |
688 | RegRefs.erase(AntiDepReg); |
689 | LastNewReg[AntiDepReg] = NewReg; |
690 | ++Broken; |
691 | } |
692 | } |
693 | |
694 | ScanInstruction(MI, Count); |
| 19 | | Calling 'CriticalAntiDepBreaker::ScanInstruction' | |
|
695 | } |
696 | |
697 | return Broken; |
698 | } |
699 | |
700 | AntiDepBreaker * |
701 | llvm::createCriticalAntiDepBreaker(MachineFunction &MFi, |
702 | const RegisterClassInfo &RCI) { |
703 | return new CriticalAntiDepBreaker(MFi, RCI); |
704 | } |
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | #ifndef LLVM_MC_MCREGISTERINFO_H |
16 | #define LLVM_MC_MCREGISTERINFO_H |
17 | |
18 | #include "llvm/ADT/DenseMap.h" |
19 | #include "llvm/ADT/iterator.h" |
20 | #include "llvm/ADT/iterator_range.h" |
21 | #include "llvm/MC/LaneBitmask.h" |
22 | #include "llvm/MC/MCRegister.h" |
23 | #include <cassert> |
24 | #include <cstdint> |
25 | #include <iterator> |
26 | #include <utility> |
27 | |
28 | namespace llvm { |
29 | |
30 | |
31 | class MCRegisterClass { |
32 | public: |
33 | using iterator = const MCPhysReg*; |
34 | using const_iterator = const MCPhysReg*; |
35 | |
36 | const iterator RegsBegin; |
37 | const uint8_t *const RegSet; |
38 | const uint32_t NameIdx; |
39 | const uint16_t RegsSize; |
40 | const uint16_t RegSetSize; |
41 | const uint16_t ID; |
42 | const uint16_t RegSizeInBits; |
43 | const int8_t CopyCost; |
44 | const bool Allocatable; |
45 | |
46 | |
47 | |
48 | unsigned getID() const { return ID; } |
49 | |
50 | |
51 | |
52 | iterator begin() const { return RegsBegin; } |
53 | iterator end() const { return RegsBegin + RegsSize; } |
54 | |
55 | |
56 | |
57 | unsigned getNumRegs() const { return RegsSize; } |
58 | |
59 | |
60 | |
61 | unsigned getRegister(unsigned i) const { |
62 | assert(i < getNumRegs() && "Register number out of range!"); |
63 | return RegsBegin[i]; |
64 | } |
65 | |
66 | |
67 | |
68 | bool contains(MCRegister Reg) const { |
69 | unsigned RegNo = unsigned(Reg); |
70 | unsigned InByte = RegNo % 8; |
71 | unsigned Byte = RegNo / 8; |
72 | if (Byte >= RegSetSize) |
73 | return false; |
74 | return (RegSet[Byte] & (1 << InByte)) != 0; |
75 | } |
76 | |
77 | |
78 | bool contains(MCRegister Reg1, MCRegister Reg2) const { |
79 | return contains(Reg1) && contains(Reg2); |
80 | } |
81 | |
82 | |
83 | |
84 | |
85 | |
86 | unsigned getSizeInBits() const { return RegSizeInBits; } |
87 | |
88 | |
89 | |
90 | |
91 | int getCopyCost() const { return CopyCost; } |
92 | |
93 | |
94 | |
95 | bool isAllocatable() const { return Allocatable; } |
96 | }; |
97 | |
98 | |
99 | |
100 | |
101 | |
102 | |
103 | |
104 | |
105 | struct MCRegisterDesc { |
106 | uint32_t Name; |
107 | uint32_t SubRegs; |
108 | uint32_t SuperRegs; |
109 | |
110 | |
111 | |
112 | uint32_t SubRegIndices; |
113 | |
114 | |
115 | |
116 | uint32_t RegUnits; |
117 | |
118 | |
119 | |
120 | uint16_t RegUnitLaneMasks; |
121 | }; |
122 | |
123 | |
124 | |
125 | |
126 | |
127 | |
128 | |
129 | |
130 | |
131 | |
132 | |
133 | |
134 | |
135 | class MCRegisterInfo { |
136 | public: |
137 | using regclass_iterator = const MCRegisterClass *; |
138 | |
139 | |
140 | |
141 | struct DwarfLLVMRegPair { |
142 | unsigned FromReg; |
143 | unsigned ToReg; |
144 | |
145 | bool operator<(DwarfLLVMRegPair RHS) const { return FromReg < RHS.FromReg; } |
146 | }; |
147 | |
148 | |
149 | |
150 | struct SubRegCoveredBits { |
151 | uint16_t Offset; |
152 | uint16_t Size; |
153 | }; |
154 | |
155 | private: |
156 | const MCRegisterDesc *Desc; |
157 | unsigned NumRegs; |
158 | MCRegister RAReg; |
159 | MCRegister PCReg; |
160 | const MCRegisterClass *Classes; |
161 | unsigned NumClasses; |
162 | unsigned NumRegUnits; |
163 | const MCPhysReg (*RegUnitRoots)[2]; |
164 | const MCPhysReg *DiffLists; |
165 | const LaneBitmask *RegUnitMaskSequences; |
166 | |
167 | const char *RegStrings; |
168 | const char *RegClassStrings; |
169 | const uint16_t *SubRegIndices; |
170 | |
171 | const SubRegCoveredBits *SubRegIdxRanges; |
172 | |
173 | unsigned NumSubRegIndices; |
174 | const uint16_t *RegEncodingTable; |
175 | |
176 | |
177 | unsigned L2DwarfRegsSize; |
178 | unsigned EHL2DwarfRegsSize; |
179 | unsigned Dwarf2LRegsSize; |
180 | unsigned EHDwarf2LRegsSize; |
181 | const DwarfLLVMRegPair *L2DwarfRegs; |
182 | const DwarfLLVMRegPair *EHL2DwarfRegs; |
183 | const DwarfLLVMRegPair *Dwarf2LRegs; |
184 | const DwarfLLVMRegPair *EHDwarf2LRegs; |
185 | DenseMap<MCRegister, int> L2SEHRegs; |
186 | DenseMap<MCRegister, int> L2CVRegs; |
187 | |
188 | public: |
189 | |
190 | template <class SubT> class mc_difflist_iterator; |
191 | |
192 | |
193 | |
194 | |
195 | |
196 | class DiffListIterator { |
197 | uint16_t Val = 0; |
198 | const MCPhysReg *List = nullptr; |
199 | |
200 | protected: |
201 | |
202 | DiffListIterator() = default; |
203 | |
204 | |
205 | |
206 | |
207 | void init(MCPhysReg InitVal, const MCPhysReg *DiffList) { |
208 | Val = InitVal; |
209 | List = DiffList; |
210 | } |
211 | |
212 | |
213 | |
214 | |
215 | MCRegister advance() { |
216 | assert(isValid() && "Cannot move off the end of the list."); |
217 | MCPhysReg D = *List++; |
| 40 | | Dereference of null pointer |
|
218 | Val += D; |
219 | return D; |
220 | } |
221 | |
222 | public: |
223 | |
224 | bool isValid() const { return List; } |
225 | |
226 | |
227 | MCRegister operator*() const { return Val; } |
228 | |
229 | |
230 | void operator++() { |
231 | |
232 | if (!advance()) |
| 39 | | Calling 'DiffListIterator::advance' | |
|
233 | List = nullptr; |
234 | } |
235 | |
236 | template <class SubT> friend class MCRegisterInfo::mc_difflist_iterator; |
237 | }; |
238 | |
239 | |
240 | template <class SubT> |
241 | class mc_difflist_iterator |
242 | : public iterator_facade_base<mc_difflist_iterator<SubT>, |
243 | std::forward_iterator_tag, MCPhysReg> { |
244 | MCRegisterInfo::DiffListIterator Iter; |
245 | |
246 | MCPhysReg Val; |
247 | |
248 | protected: |
249 | mc_difflist_iterator(MCRegisterInfo::DiffListIterator Iter) : Iter(Iter) {} |
250 | |
251 | |
252 | mc_difflist_iterator(MCRegister Reg, const MCPhysReg *DiffList) { |
253 | Iter.init(Reg, DiffList); |
254 | Val = *Iter; |
255 | } |
256 | |
257 | public: |
258 | |
259 | |
260 | mc_difflist_iterator() = default; |
261 | |
262 | |
263 | static SubT end() { |
264 | SubT End; |
265 | End.Iter.List = nullptr; |
266 | return End; |
267 | } |
268 | |
269 | bool operator==(const mc_difflist_iterator &Arg) const { |
270 | return Iter.List == Arg.Iter.List; |
271 | } |
272 | |
273 | const MCPhysReg &operator*() const { return Val; } |
274 | |
275 | using mc_difflist_iterator::iterator_facade_base::operator++; |
276 | void operator++() { |
277 | assert(Iter.List && "Cannot increment the end iterator!"); |
278 | ++Iter; |
279 | Val = *Iter; |
280 | } |
281 | }; |
282 | |
283 | |
284 | |
285 | class mc_subreg_iterator : public mc_difflist_iterator<mc_subreg_iterator> { |
286 | public: |
287 | mc_subreg_iterator(MCRegisterInfo::DiffListIterator Iter) |
288 | : mc_difflist_iterator(Iter) {} |
289 | mc_subreg_iterator() = default; |
290 | mc_subreg_iterator(MCRegister Reg, const MCRegisterInfo *MCRI) |
291 | : mc_difflist_iterator(Reg, MCRI->DiffLists + MCRI->get(Reg).SubRegs) {} |
292 | }; |
293 | |
294 | |
295 | |
296 | class mc_superreg_iterator |
297 | : public mc_difflist_iterator<mc_superreg_iterator> { |
298 | public: |
299 | mc_superreg_iterator(MCRegisterInfo::DiffListIterator Iter) |
300 | : mc_difflist_iterator(Iter) {} |
301 | mc_superreg_iterator() = default; |
302 | mc_superreg_iterator(MCRegister Reg, const MCRegisterInfo *MCRI) |
303 | : mc_difflist_iterator(Reg, |
304 | MCRI->DiffLists + MCRI->get(Reg).SuperRegs) {} |
305 | }; |
306 | |
307 | |
308 | |
309 | iterator_range<mc_subreg_iterator> subregs(MCRegister Reg) const { |
310 | return make_range(std::next(mc_subreg_iterator(Reg, this)), |
311 | mc_subreg_iterator::end()); |
312 | } |
313 | |
314 | |
315 | |
316 | iterator_range<mc_subreg_iterator> subregs_inclusive(MCRegister Reg) const { |
317 | return make_range({Reg, this}, mc_subreg_iterator::end()); |
318 | } |
319 | |
320 | |
321 | |
322 | iterator_range<mc_superreg_iterator> superregs(MCRegister Reg) const { |
323 | return make_range(std::next(mc_superreg_iterator(Reg, this)), |
324 | mc_superreg_iterator::end()); |
325 | } |
326 | |
327 | |
328 | |
329 | iterator_range<mc_superreg_iterator> |
330 | superregs_inclusive(MCRegister Reg) const { |
331 | return make_range({Reg, this}, mc_superreg_iterator::end()); |
332 | } |
333 | |
334 | |
335 | |
336 | detail::concat_range<const MCPhysReg, iterator_range<mc_subreg_iterator>, |
337 | iterator_range<mc_superreg_iterator>> |
338 | sub_and_superregs_inclusive(MCRegister Reg) const { |
339 | return concat<const MCPhysReg>(subregs_inclusive(Reg), superregs(Reg)); |
340 | } |
341 | |
342 | |
343 | |
344 | friend class MCSubRegIterator; |
345 | friend class MCSubRegIndexIterator; |
346 | friend class MCSuperRegIterator; |
347 | friend class MCRegUnitIterator; |
348 | friend class MCRegUnitMaskIterator; |
349 | friend class MCRegUnitRootIterator; |
350 | |
351 | |
352 | |
353 | void InitMCRegisterInfo(const MCRegisterDesc *D, unsigned NR, unsigned RA, |
354 | unsigned PC, |
355 | const MCRegisterClass *C, unsigned NC, |
356 | const MCPhysReg (*RURoots)[2], |
357 | unsigned NRU, |
358 | const MCPhysReg *DL, |
359 | const LaneBitmask *RUMS, |
360 | const char *Strings, |
361 | const char *ClassStrings, |
362 | const uint16_t *SubIndices, |
363 | unsigned NumIndices, |
364 | const SubRegCoveredBits *SubIdxRanges, |
365 | const uint16_t *RET) { |
366 | Desc = D; |
367 | NumRegs = NR; |
368 | RAReg = RA; |
369 | PCReg = PC; |
370 | Classes = C; |
371 | DiffLists = DL; |
372 | RegUnitMaskSequences = RUMS; |
373 | RegStrings = Strings; |
374 | RegClassStrings = ClassStrings; |
375 | NumClasses = NC; |
376 | RegUnitRoots = RURoots; |
377 | NumRegUnits = NRU; |
378 | SubRegIndices = SubIndices; |
379 | NumSubRegIndices = NumIndices; |
380 | SubRegIdxRanges = SubIdxRanges; |
381 | RegEncodingTable = RET; |
382 | |
383 | |
384 | EHL2DwarfRegs = nullptr; |
385 | EHL2DwarfRegsSize = 0; |
386 | L2DwarfRegs = nullptr; |
387 | L2DwarfRegsSize = 0; |
388 | EHDwarf2LRegs = nullptr; |
389 | EHDwarf2LRegsSize = 0; |
390 | Dwarf2LRegs = nullptr; |
391 | Dwarf2LRegsSize = 0; |
392 | } |
393 | |
394 | |
395 | |
396 | |
397 | void mapLLVMRegsToDwarfRegs(const DwarfLLVMRegPair *Map, unsigned Size, |
398 | bool isEH) { |
399 | if (isEH) { |
400 | EHL2DwarfRegs = Map; |
401 | EHL2DwarfRegsSize = Size; |
402 | } else { |
403 | L2DwarfRegs = Map; |
404 | L2DwarfRegsSize = Size; |
405 | } |
406 | } |
407 | |
408 | |
409 | |
410 | |
411 | void mapDwarfRegsToLLVMRegs(const DwarfLLVMRegPair *Map, unsigned Size, |
412 | bool isEH) { |
413 | if (isEH) { |
414 | EHDwarf2LRegs = Map; |
415 | EHDwarf2LRegsSize = Size; |
416 | } else { |
417 | Dwarf2LRegs = Map; |
418 | Dwarf2LRegsSize = Size; |
419 | } |
420 | } |
421 | |
422 | |
423 | |
424 | |
425 | |
426 | |
427 | void mapLLVMRegToSEHReg(MCRegister LLVMReg, int SEHReg) { |
428 | L2SEHRegs[LLVMReg] = SEHReg; |
429 | } |
430 | |
431 | void mapLLVMRegToCVReg(MCRegister LLVMReg, int CVReg) { |
432 | L2CVRegs[LLVMReg] = CVReg; |
433 | } |
434 | |
435 | |
436 | |
437 | MCRegister getRARegister() const { |
438 | return RAReg; |
439 | } |
440 | |
441 | |
442 | MCRegister getProgramCounter() const { |
443 | return PCReg; |
444 | } |
445 | |
446 | const MCRegisterDesc &operator[](MCRegister RegNo) const { |
447 | assert(RegNo < NumRegs && |
448 | "Attempting to access record for invalid register number!"); |
449 | return Desc[RegNo]; |
450 | } |
451 | |
452 | |
453 | |
454 | const MCRegisterDesc &get(MCRegister RegNo) const { |
455 | return operator[](RegNo); |
456 | } |
457 | |
458 | |
459 | |
460 | |
461 | MCRegister getSubReg(MCRegister Reg, unsigned Idx) const; |
462 | |
463 | |
464 | |
465 | MCRegister getMatchingSuperReg(MCRegister Reg, unsigned SubIdx, |
466 | const MCRegisterClass *RC) const; |
467 | |
468 | |
469 | |
470 | |
471 | unsigned getSubRegIndex(MCRegister RegNo, MCRegister SubRegNo) const; |
472 | |
473 | |
474 | |
475 | |
476 | unsigned getSubRegIdxSize(unsigned Idx) const; |
477 | |
478 | |
479 | |
480 | |
481 | unsigned getSubRegIdxOffset(unsigned Idx) const; |
482 | |
483 | |
484 | |
485 | const char *getName(MCRegister RegNo) const { |
486 | return RegStrings + get(RegNo).Name; |
487 | } |
488 | |
489 | |
490 | |
491 | unsigned getNumRegs() const { |
492 | return NumRegs; |
493 | } |
494 | |
495 | |
496 | |
497 | |
498 | unsigned getNumSubRegIndices() const { |
499 | return NumSubRegIndices; |
500 | } |
501 | |
502 | |
503 | |
504 | |
505 | unsigned getNumRegUnits() const { |
506 | return NumRegUnits; |
507 | } |
508 | |
509 | |
510 | |
511 | |
512 | |
513 | int getDwarfRegNum(MCRegister RegNum, bool isEH) const; |
514 | |
515 | |
516 | |
517 | Optional<unsigned> getLLVMRegNum(unsigned RegNum, bool isEH) const; |
518 | |
519 | |
520 | |
521 | int getDwarfRegNumFromDwarfEHRegNum(unsigned RegNum) const; |
522 | |
523 | |
524 | |
525 | int getSEHRegNum(MCRegister RegNum) const; |
526 | |
527 | |
528 | |
529 | int getCodeViewRegNum(MCRegister RegNum) const; |
530 | |
531 | regclass_iterator regclass_begin() const { return Classes; } |
532 | regclass_iterator regclass_end() const { return Classes+NumClasses; } |
533 | iterator_range<regclass_iterator> regclasses() const { |
534 | return make_range(regclass_begin(), regclass_end()); |
535 | } |
536 | |
537 | unsigned getNumRegClasses() const { |
538 | return (unsigned)(regclass_end()-regclass_begin()); |
539 | } |
540 | |
541 | |
542 | |
543 | const MCRegisterClass& getRegClass(unsigned i) const { |
544 | assert(i < getNumRegClasses() && "Register Class ID out of range"); |
545 | return Classes[i]; |
546 | } |
547 | |
548 | const char *getRegClassName(const MCRegisterClass *Class) const { |
549 | return RegClassStrings + Class->NameIdx; |
550 | } |
551 | |
552 | |
553 | uint16_t getEncodingValue(MCRegister RegNo) const { |
554 | assert(RegNo < NumRegs && |
555 | "Attempting to get encoding for invalid register number!"); |
556 | return RegEncodingTable[RegNo]; |
557 | } |
558 | |
559 | |
560 | bool isSubRegister(MCRegister RegA, MCRegister RegB) const { |
561 | return isSuperRegister(RegB, RegA); |
562 | } |
563 | |
564 | |
565 | bool isSuperRegister(MCRegister RegA, MCRegister RegB) const; |
566 | |
567 | |
568 | bool isSubRegisterEq(MCRegister RegA, MCRegister RegB) const { |
569 | return isSuperRegisterEq(RegB, RegA); |
570 | } |
571 | |
572 | |
573 | |
574 | bool isSuperRegisterEq(MCRegister RegA, MCRegister RegB) const { |
575 | return RegA == RegB || isSuperRegister(RegA, RegB); |
576 | } |
577 | |
578 | |
579 | |
580 | bool isSuperOrSubRegisterEq(MCRegister RegA, MCRegister RegB) const { |
581 | return isSubRegisterEq(RegA, RegB) || isSuperRegister(RegA, RegB); |
582 | } |
583 | }; |
584 | |
585 | |
586 | |
587 | |
588 | |
589 | |
590 | |
591 | |
592 | |
593 | |
594 | class MCSubRegIterator : public MCRegisterInfo::DiffListIterator { |
595 | public: |
596 | MCSubRegIterator(MCRegister Reg, const MCRegisterInfo *MCRI, |
597 | bool IncludeSelf = false) { |
598 | init(Reg, MCRI->DiffLists + MCRI->get(Reg).SubRegs); |
599 | |
600 | if (!IncludeSelf) |
601 | ++*this; |
602 | } |
603 | }; |
604 | |
605 | |
606 | |
607 | class MCSubRegIndexIterator { |
608 | MCSubRegIterator SRIter; |
609 | const uint16_t *SRIndex; |
610 | |
611 | public: |
612 | |
613 | |
614 | MCSubRegIndexIterator(MCRegister Reg, const MCRegisterInfo *MCRI) |
615 | : SRIter(Reg, MCRI) { |
616 | SRIndex = MCRI->SubRegIndices + MCRI->get(Reg).SubRegIndices; |
617 | } |
618 | |
619 | |
620 | MCRegister getSubReg() const { |
621 | return *SRIter; |
622 | } |
623 | |
624 | |
625 | unsigned getSubRegIndex() const { |
626 | return *SRIndex; |
627 | } |
628 | |
629 | |
630 | bool isValid() const { return SRIter.isValid(); } |
631 | |
632 | |
633 | void operator++() { |
634 | ++SRIter; |
635 | ++SRIndex; |
636 | } |
637 | }; |
638 | |
639 | |
640 | |
641 | class MCSuperRegIterator : public MCRegisterInfo::DiffListIterator { |
642 | public: |
643 | MCSuperRegIterator() = default; |
644 | |
645 | MCSuperRegIterator(MCRegister Reg, const MCRegisterInfo *MCRI, |
646 | bool IncludeSelf = false) { |
647 | init(Reg, MCRI->DiffLists + MCRI->get(Reg).SuperRegs); |
648 | |
649 | if (!IncludeSelf) |
| |
650 | ++*this; |
| 38 | | Calling 'DiffListIterator::operator++' | |
|
651 | } |
652 | }; |
653 | |
654 | |
655 | |
656 | inline bool MCRegisterInfo::isSuperRegister(MCRegister RegA, MCRegister RegB) const{ |
657 | for (MCSuperRegIterator I(RegA, this); I.isValid(); ++I) |
658 | if (*I == RegB) |
659 | return true; |
660 | return false; |
661 | } |
662 | |
663 | |
664 | |
665 | |
666 | |
667 | |
668 | |
669 | |
670 | |
671 | |
672 | |
673 | |
674 | |
675 | |
676 | |
677 | class MCRegUnitIterator : public MCRegisterInfo::DiffListIterator { |
678 | public: |
679 | |
680 | |
681 | MCRegUnitIterator() = default; |
682 | |
683 | MCRegUnitIterator(MCRegister Reg, const MCRegisterInfo *MCRI) { |
684 | assert(Reg && "Null register has no regunits"); |
685 | assert(MCRegister::isPhysicalRegister(Reg.id())); |
686 | |
687 | unsigned RU = MCRI->get(Reg).RegUnits; |
688 | unsigned Scale = RU & 15; |
689 | unsigned Offset = RU >> 4; |
690 | |
691 | |
692 | |
693 | init(Reg * Scale, MCRI->DiffLists + Offset); |
694 | |
695 | |
696 | |
697 | |
698 | |
699 | advance(); |
700 | } |
701 | }; |
702 | |
703 | |
704 | |
705 | |
706 | class MCRegUnitMaskIterator { |
707 | MCRegUnitIterator RUIter; |
708 | const LaneBitmask *MaskListIter; |
709 | |
710 | public: |
711 | MCRegUnitMaskIterator() = default; |
712 | |
713 | |
714 | |
715 | MCRegUnitMaskIterator(MCRegister Reg, const MCRegisterInfo *MCRI) |
716 | : RUIter(Reg, MCRI) { |
717 | uint16_t Idx = MCRI->get(Reg).RegUnitLaneMasks; |
718 | MaskListIter = &MCRI->RegUnitMaskSequences[Idx]; |
719 | } |
720 | |
721 | |
722 | std::pair<unsigned,LaneBitmask> operator*() const { |
723 | return std::make_pair(*RUIter, *MaskListIter); |
724 | } |
725 | |
726 | |
727 | bool isValid() const { return RUIter.isValid(); } |
728 | |
729 | |
730 | void operator++() { |
731 | ++MaskListIter; |
732 | ++RUIter; |
733 | } |
734 | }; |
735 | |
736 | |
737 | |
738 | |
739 | |
740 | |
741 | |
742 | |
743 | |
744 | |
745 | |
746 | class MCRegUnitRootIterator { |
747 | uint16_t Reg0 = 0; |
748 | uint16_t Reg1 = 0; |
749 | |
750 | public: |
751 | MCRegUnitRootIterator() = default; |
752 | |
753 | MCRegUnitRootIterator(unsigned RegUnit, const MCRegisterInfo *MCRI) { |
754 | assert(RegUnit < MCRI->getNumRegUnits() && "Invalid register unit"); |
755 | Reg0 = MCRI->RegUnitRoots[RegUnit][0]; |
756 | Reg1 = MCRI->RegUnitRoots[RegUnit][1]; |
757 | } |
758 | |
759 | |
760 | unsigned operator*() const { |
761 | return Reg0; |
762 | } |
763 | |
764 | |
765 | bool isValid() const { |
766 | return Reg0; |
767 | } |
768 | |
769 | |
770 | void operator++() { |
771 | assert(isValid() && "Cannot move off the end of the list."); |
772 | Reg0 = Reg1; |
773 | Reg1 = 0; |
774 | } |
775 | }; |
776 | |
777 | |
778 | |
779 | |
780 | class MCRegAliasIterator { |
781 | private: |
782 | MCRegister Reg; |
783 | const MCRegisterInfo *MCRI; |
784 | bool IncludeSelf; |
785 | |
786 | MCRegUnitIterator RI; |
787 | MCRegUnitRootIterator RRI; |
788 | MCSuperRegIterator SI; |
789 | |
790 | public: |
791 | MCRegAliasIterator(MCRegister Reg, const MCRegisterInfo *MCRI, |
792 | bool IncludeSelf) |
793 | : Reg(Reg), MCRI(MCRI), IncludeSelf(IncludeSelf) { |
794 | |
795 | for (RI = MCRegUnitIterator(Reg, MCRI); RI.isValid(); ++RI) { |
796 | for (RRI = MCRegUnitRootIterator(*RI, MCRI); RRI.isValid(); ++RRI) { |
797 | for (SI = MCSuperRegIterator(*RRI, MCRI, true); SI.isValid(); ++SI) { |
798 | if (!(!IncludeSelf && Reg == *SI)) |
799 | return; |
800 | } |
801 | } |
802 | } |
803 | } |
804 | |
805 | bool isValid() const { return RI.isValid(); } |
806 | |
807 | MCRegister operator*() const { |
808 | assert(SI.isValid() && "Cannot dereference an invalid iterator."); |
809 | return *SI; |
810 | } |
811 | |
812 | void advance() { |
813 | |
814 | ++SI; |
815 | if (SI.isValid()) return; |
816 | |
817 | ++RRI; |
818 | if (RRI.isValid()) { |
819 | SI = MCSuperRegIterator(*RRI, MCRI, true); |
820 | return; |
821 | } |
822 | |
823 | ++RI; |
824 | if (RI.isValid()) { |
825 | RRI = MCRegUnitRootIterator(*RI, MCRI); |
826 | SI = MCSuperRegIterator(*RRI, MCRI, true); |
827 | } |
828 | } |
829 | |
830 | void operator++() { |
831 | assert(isValid() && "Cannot move off the end of the list."); |
832 | do advance(); |
833 | while (!IncludeSelf && isValid() && *SI == Reg); |
834 | } |
835 | }; |
836 | |
837 | } |
838 | |
839 | #endif // LLVM_MC_MCREGISTERINFO_H |