File: | tools/llvm-exegesis/lib/MCInstrDescView.cpp |
Warning: | line 235, column 44 Access to field 'RegClass' results in a dereference of a null pointer (loaded from field 'Info') |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===-- MCInstrDescView.cpp -------------------------------------*- C++ -*-===// | |||
2 | // | |||
3 | // The LLVM Compiler Infrastructure | |||
4 | // | |||
5 | // This file is distributed under the University of Illinois Open Source | |||
6 | // License. See LICENSE.TXT for details. | |||
7 | // | |||
8 | //===----------------------------------------------------------------------===// | |||
9 | ||||
10 | #include "MCInstrDescView.h" | |||
11 | ||||
12 | #include <iterator> | |||
13 | #include <map> | |||
14 | #include <tuple> | |||
15 | ||||
16 | #include "llvm/ADT/STLExtras.h" | |||
17 | ||||
18 | namespace llvm { | |||
19 | namespace exegesis { | |||
20 | ||||
21 | unsigned Variable::getIndex() const { | |||
22 | assert(Index >= 0 && "Index must be set")((Index >= 0 && "Index must be set") ? static_cast <void> (0) : __assert_fail ("Index >= 0 && \"Index must be set\"" , "/build/llvm-toolchain-snapshot-8~svn345461/tools/llvm-exegesis/lib/MCInstrDescView.cpp" , 22, __PRETTY_FUNCTION__)); | |||
23 | return Index; | |||
24 | } | |||
25 | ||||
26 | unsigned Variable::getPrimaryOperandIndex() const { | |||
27 | assert(!TiedOperands.empty())((!TiedOperands.empty()) ? static_cast<void> (0) : __assert_fail ("!TiedOperands.empty()", "/build/llvm-toolchain-snapshot-8~svn345461/tools/llvm-exegesis/lib/MCInstrDescView.cpp" , 27, __PRETTY_FUNCTION__)); | |||
28 | return TiedOperands[0]; | |||
29 | } | |||
30 | ||||
31 | bool Variable::hasTiedOperands() const { | |||
32 | assert(TiedOperands.size() <= 2 &&((TiedOperands.size() <= 2 && "No more than two operands can be tied together" ) ? static_cast<void> (0) : __assert_fail ("TiedOperands.size() <= 2 && \"No more than two operands can be tied together\"" , "/build/llvm-toolchain-snapshot-8~svn345461/tools/llvm-exegesis/lib/MCInstrDescView.cpp" , 33, __PRETTY_FUNCTION__)) | |||
33 | "No more than two operands can be tied together")((TiedOperands.size() <= 2 && "No more than two operands can be tied together" ) ? static_cast<void> (0) : __assert_fail ("TiedOperands.size() <= 2 && \"No more than two operands can be tied together\"" , "/build/llvm-toolchain-snapshot-8~svn345461/tools/llvm-exegesis/lib/MCInstrDescView.cpp" , 33, __PRETTY_FUNCTION__)); | |||
34 | // By definition only Use and Def operands can be tied together. | |||
35 | // TiedOperands[0] is the Def operand (LLVM stores defs first). | |||
36 | // TiedOperands[1] is the Use operand. | |||
37 | return TiedOperands.size() > 1; | |||
38 | } | |||
39 | ||||
40 | unsigned Operand::getIndex() const { | |||
41 | assert(Index >= 0 && "Index must be set")((Index >= 0 && "Index must be set") ? static_cast <void> (0) : __assert_fail ("Index >= 0 && \"Index must be set\"" , "/build/llvm-toolchain-snapshot-8~svn345461/tools/llvm-exegesis/lib/MCInstrDescView.cpp" , 41, __PRETTY_FUNCTION__)); | |||
42 | return Index; | |||
43 | } | |||
44 | ||||
45 | bool Operand::isExplicit() const { return Info; } | |||
46 | ||||
47 | bool Operand::isImplicit() const { return !Info; } | |||
48 | ||||
49 | bool Operand::isImplicitReg() const { return ImplicitReg; } | |||
50 | ||||
51 | bool Operand::isDef() const { return IsDef; } | |||
52 | ||||
53 | bool Operand::isUse() const { return !IsDef; } | |||
54 | ||||
55 | bool Operand::isReg() const { return Tracker; } | |||
56 | ||||
57 | bool Operand::isTied() const { return TiedToIndex >= 0; } | |||
58 | ||||
59 | bool Operand::isVariable() const { return VariableIndex >= 0; } | |||
60 | ||||
61 | bool Operand::isMemory() const { | |||
62 | return isExplicit() && | |||
63 | getExplicitOperandInfo().OperandType == llvm::MCOI::OPERAND_MEMORY; | |||
64 | } | |||
65 | ||||
66 | bool Operand::isImmediate() const { | |||
67 | return isExplicit() && | |||
68 | getExplicitOperandInfo().OperandType == llvm::MCOI::OPERAND_IMMEDIATE; | |||
69 | } | |||
70 | ||||
71 | unsigned Operand::getTiedToIndex() const { | |||
72 | assert(isTied() && "Operand must be tied to get the tied index")((isTied() && "Operand must be tied to get the tied index" ) ? static_cast<void> (0) : __assert_fail ("isTied() && \"Operand must be tied to get the tied index\"" , "/build/llvm-toolchain-snapshot-8~svn345461/tools/llvm-exegesis/lib/MCInstrDescView.cpp" , 72, __PRETTY_FUNCTION__)); | |||
73 | assert(TiedToIndex >= 0 && "TiedToIndex must be set")((TiedToIndex >= 0 && "TiedToIndex must be set") ? static_cast<void> (0) : __assert_fail ("TiedToIndex >= 0 && \"TiedToIndex must be set\"" , "/build/llvm-toolchain-snapshot-8~svn345461/tools/llvm-exegesis/lib/MCInstrDescView.cpp" , 73, __PRETTY_FUNCTION__)); | |||
74 | return TiedToIndex; | |||
75 | } | |||
76 | ||||
77 | unsigned Operand::getVariableIndex() const { | |||
78 | assert(isVariable() && "Operand must be variable to get the Variable index")((isVariable() && "Operand must be variable to get the Variable index" ) ? static_cast<void> (0) : __assert_fail ("isVariable() && \"Operand must be variable to get the Variable index\"" , "/build/llvm-toolchain-snapshot-8~svn345461/tools/llvm-exegesis/lib/MCInstrDescView.cpp" , 78, __PRETTY_FUNCTION__)); | |||
79 | assert(VariableIndex >= 0 && "VariableIndex must be set")((VariableIndex >= 0 && "VariableIndex must be set" ) ? static_cast<void> (0) : __assert_fail ("VariableIndex >= 0 && \"VariableIndex must be set\"" , "/build/llvm-toolchain-snapshot-8~svn345461/tools/llvm-exegesis/lib/MCInstrDescView.cpp" , 79, __PRETTY_FUNCTION__)); | |||
80 | return VariableIndex; | |||
81 | } | |||
82 | ||||
83 | unsigned Operand::getImplicitReg() const { | |||
84 | assert(ImplicitReg)((ImplicitReg) ? static_cast<void> (0) : __assert_fail ( "ImplicitReg", "/build/llvm-toolchain-snapshot-8~svn345461/tools/llvm-exegesis/lib/MCInstrDescView.cpp" , 84, __PRETTY_FUNCTION__)); | |||
85 | return *ImplicitReg; | |||
86 | } | |||
87 | ||||
88 | const RegisterAliasingTracker &Operand::getRegisterAliasing() const { | |||
89 | assert(Tracker)((Tracker) ? static_cast<void> (0) : __assert_fail ("Tracker" , "/build/llvm-toolchain-snapshot-8~svn345461/tools/llvm-exegesis/lib/MCInstrDescView.cpp" , 89, __PRETTY_FUNCTION__)); | |||
90 | return *Tracker; | |||
91 | } | |||
92 | ||||
93 | const llvm::MCOperandInfo &Operand::getExplicitOperandInfo() const { | |||
94 | assert(Info)((Info) ? static_cast<void> (0) : __assert_fail ("Info" , "/build/llvm-toolchain-snapshot-8~svn345461/tools/llvm-exegesis/lib/MCInstrDescView.cpp" , 94, __PRETTY_FUNCTION__)); | |||
95 | return *Info; | |||
96 | } | |||
97 | ||||
98 | Instruction::Instruction(const llvm::MCInstrInfo &InstrInfo, | |||
99 | const RegisterAliasingTrackerCache &RATC, | |||
100 | unsigned Opcode) | |||
101 | : Description(&InstrInfo.get(Opcode)), Name(InstrInfo.getName(Opcode)) { | |||
102 | unsigned OpIndex = 0; | |||
103 | for (; OpIndex < Description->getNumOperands(); ++OpIndex) { | |||
104 | const auto &OpInfo = Description->opInfo_begin()[OpIndex]; | |||
105 | Operand Operand; | |||
106 | Operand.Index = OpIndex; | |||
107 | Operand.IsDef = (OpIndex < Description->getNumDefs()); | |||
108 | // TODO(gchatelet): Handle isLookupPtrRegClass. | |||
109 | if (OpInfo.RegClass >= 0) | |||
110 | Operand.Tracker = &RATC.getRegisterClass(OpInfo.RegClass); | |||
111 | Operand.TiedToIndex = | |||
112 | Description->getOperandConstraint(OpIndex, llvm::MCOI::TIED_TO); | |||
113 | Operand.Info = &OpInfo; | |||
114 | Operands.push_back(Operand); | |||
115 | } | |||
116 | for (const llvm::MCPhysReg *MCPhysReg = Description->getImplicitDefs(); | |||
117 | MCPhysReg && *MCPhysReg; ++MCPhysReg, ++OpIndex) { | |||
118 | Operand Operand; | |||
119 | Operand.Index = OpIndex; | |||
120 | Operand.IsDef = true; | |||
121 | Operand.Tracker = &RATC.getRegister(*MCPhysReg); | |||
122 | Operand.ImplicitReg = MCPhysReg; | |||
123 | Operands.push_back(Operand); | |||
124 | } | |||
125 | for (const llvm::MCPhysReg *MCPhysReg = Description->getImplicitUses(); | |||
126 | MCPhysReg && *MCPhysReg; ++MCPhysReg, ++OpIndex) { | |||
127 | Operand Operand; | |||
128 | Operand.Index = OpIndex; | |||
129 | Operand.IsDef = false; | |||
130 | Operand.Tracker = &RATC.getRegister(*MCPhysReg); | |||
131 | Operand.ImplicitReg = MCPhysReg; | |||
132 | Operands.push_back(Operand); | |||
133 | } | |||
134 | // Assigning Variables to non tied explicit operands. | |||
135 | Variables.reserve(Operands.size()); // Variables.size() <= Operands.size() | |||
136 | for (auto &Op : Operands) | |||
137 | if (Op.isExplicit() && !Op.isTied()) { | |||
138 | const size_t VariableIndex = Variables.size(); | |||
139 | Op.VariableIndex = VariableIndex; | |||
140 | Variables.emplace_back(); | |||
141 | Variables.back().Index = VariableIndex; | |||
142 | } | |||
143 | // Assigning Variables to tied operands. | |||
144 | for (auto &Op : Operands) | |||
145 | if (Op.isTied()) | |||
146 | Op.VariableIndex = Operands[Op.getTiedToIndex()].getVariableIndex(); | |||
147 | // Assigning Operands to Variables. | |||
148 | for (auto &Op : Operands) | |||
149 | if (Op.isVariable()) | |||
150 | Variables[Op.getVariableIndex()].TiedOperands.push_back(Op.getIndex()); | |||
151 | // Processing Aliasing. | |||
152 | ImplDefRegs = RATC.emptyRegisters(); | |||
153 | ImplUseRegs = RATC.emptyRegisters(); | |||
154 | AllDefRegs = RATC.emptyRegisters(); | |||
155 | AllUseRegs = RATC.emptyRegisters(); | |||
156 | for (const auto &Op : Operands) { | |||
157 | if (Op.isReg()) { | |||
158 | const auto &AliasingBits = Op.getRegisterAliasing().aliasedBits(); | |||
159 | if (Op.isDef()) | |||
160 | AllDefRegs |= AliasingBits; | |||
161 | if (Op.isUse()) | |||
162 | AllUseRegs |= AliasingBits; | |||
163 | if (Op.isDef() && Op.isImplicit()) | |||
164 | ImplDefRegs |= AliasingBits; | |||
165 | if (Op.isUse() && Op.isImplicit()) | |||
166 | ImplUseRegs |= AliasingBits; | |||
167 | } | |||
168 | } | |||
169 | } | |||
170 | ||||
171 | const Operand &Instruction::getPrimaryOperand(const Variable &Var) const { | |||
172 | const auto PrimaryOperandIndex = Var.getPrimaryOperandIndex(); | |||
173 | assert(PrimaryOperandIndex < Operands.size())((PrimaryOperandIndex < Operands.size()) ? static_cast< void> (0) : __assert_fail ("PrimaryOperandIndex < Operands.size()" , "/build/llvm-toolchain-snapshot-8~svn345461/tools/llvm-exegesis/lib/MCInstrDescView.cpp" , 173, __PRETTY_FUNCTION__)); | |||
174 | return Operands[PrimaryOperandIndex]; | |||
175 | } | |||
176 | ||||
177 | bool Instruction::hasMemoryOperands() const { | |||
178 | return any_of(Operands, [](const Operand &Op) { | |||
179 | return Op.isReg() && Op.isExplicit() && Op.isMemory(); | |||
180 | }); | |||
181 | } | |||
182 | ||||
183 | bool Instruction::hasAliasingImplicitRegisters() const { | |||
184 | return ImplDefRegs.anyCommon(ImplUseRegs); | |||
185 | } | |||
186 | ||||
187 | bool Instruction::hasAliasingImplicitRegistersThrough( | |||
188 | const Instruction &OtherInstr) const { | |||
189 | return ImplDefRegs.anyCommon(OtherInstr.ImplUseRegs) && | |||
190 | OtherInstr.ImplDefRegs.anyCommon(ImplUseRegs); | |||
191 | } | |||
192 | ||||
193 | bool Instruction::hasAliasingRegistersThrough( | |||
194 | const Instruction &OtherInstr) const { | |||
195 | return AllDefRegs.anyCommon(OtherInstr.AllUseRegs) && | |||
196 | OtherInstr.AllDefRegs.anyCommon(AllUseRegs); | |||
197 | } | |||
198 | ||||
199 | bool Instruction::hasTiedRegisters() const { | |||
200 | return llvm::any_of( | |||
201 | Variables, [](const Variable &Var) { return Var.hasTiedOperands(); }); | |||
202 | } | |||
203 | ||||
204 | bool Instruction::hasAliasingRegisters() const { | |||
205 | return AllDefRegs.anyCommon(AllUseRegs); | |||
206 | } | |||
207 | ||||
208 | bool Instruction::hasOneUseOrOneDef() const { | |||
209 | return AllDefRegs.count() || AllUseRegs.count(); | |||
210 | } | |||
211 | ||||
212 | void Instruction::dump(const llvm::MCRegisterInfo &RegInfo, | |||
213 | llvm::raw_ostream &Stream) const { | |||
214 | Stream << "- " << Name << "\n"; | |||
215 | for (const auto &Op : Operands) { | |||
| ||||
216 | Stream << "- Op" << Op.getIndex(); | |||
217 | if (Op.isExplicit()) | |||
218 | Stream << " Explicit"; | |||
219 | if (Op.isImplicit()) | |||
220 | Stream << " Implicit"; | |||
221 | if (Op.isUse()) | |||
222 | Stream << " Use"; | |||
223 | if (Op.isDef()) | |||
224 | Stream << " Def"; | |||
225 | if (Op.isImmediate()) | |||
226 | Stream << " Immediate"; | |||
227 | if (Op.isMemory()) | |||
228 | Stream << " Memory"; | |||
229 | if (Op.isReg()) { | |||
230 | if (Op.isImplicitReg()) | |||
231 | Stream << " Reg(" << RegInfo.getName(Op.getImplicitReg()) << ")"; | |||
232 | else | |||
233 | Stream << " RegClass(" | |||
234 | << RegInfo.getRegClassName( | |||
235 | &RegInfo.getRegClass(Op.Info->RegClass)) | |||
| ||||
236 | << ")"; | |||
237 | } | |||
238 | if (Op.isTied()) | |||
239 | Stream << " TiedToOp" << Op.getTiedToIndex(); | |||
240 | Stream << "\n"; | |||
241 | } | |||
242 | for (const auto &Var : Variables) { | |||
243 | Stream << "- Var" << Var.getIndex(); | |||
244 | Stream << " ["; | |||
245 | bool IsFirst = true; | |||
246 | for (auto OperandIndex : Var.TiedOperands) { | |||
247 | if (!IsFirst) | |||
248 | Stream << ","; | |||
249 | Stream << "Op" << OperandIndex; | |||
250 | IsFirst = false; | |||
251 | } | |||
252 | Stream << "]"; | |||
253 | Stream << "\n"; | |||
254 | } | |||
255 | if (hasMemoryOperands()) | |||
256 | Stream << "- hasMemoryOperands\n"; | |||
257 | if (hasAliasingImplicitRegisters()) | |||
258 | Stream << "- hasAliasingImplicitRegisters (execution is always serial)\n"; | |||
259 | if (hasTiedRegisters()) | |||
260 | Stream << "- hasTiedRegisters (execution is always serial)\n"; | |||
261 | if (hasAliasingRegisters()) | |||
262 | Stream << "- hasAliasingRegisters\n"; | |||
263 | } | |||
264 | ||||
265 | InstructionsCache::InstructionsCache(const llvm::MCInstrInfo &InstrInfo, | |||
266 | const RegisterAliasingTrackerCache &RATC) | |||
267 | : InstrInfo(InstrInfo), RATC(RATC) {} | |||
268 | ||||
269 | const Instruction &InstructionsCache::getInstr(unsigned Opcode) const { | |||
270 | auto &Found = Instructions[Opcode]; | |||
271 | if (!Found) | |||
272 | Found.reset(new Instruction(InstrInfo, RATC, Opcode)); | |||
273 | return *Found; | |||
274 | } | |||
275 | ||||
276 | bool RegisterOperandAssignment:: | |||
277 | operator==(const RegisterOperandAssignment &Other) const { | |||
278 | return std::tie(Op, Reg) == std::tie(Other.Op, Other.Reg); | |||
279 | } | |||
280 | ||||
281 | bool AliasingRegisterOperands:: | |||
282 | operator==(const AliasingRegisterOperands &Other) const { | |||
283 | return std::tie(Defs, Uses) == std::tie(Other.Defs, Other.Uses); | |||
284 | } | |||
285 | ||||
286 | static void addOperandIfAlias( | |||
287 | const llvm::MCPhysReg Reg, bool SelectDef, llvm::ArrayRef<Operand> Operands, | |||
288 | llvm::SmallVectorImpl<RegisterOperandAssignment> &OperandValues) { | |||
289 | for (const auto &Op : Operands) { | |||
290 | if (Op.isReg() && Op.isDef() == SelectDef) { | |||
291 | const int SourceReg = Op.getRegisterAliasing().getOrigin(Reg); | |||
292 | if (SourceReg >= 0) | |||
293 | OperandValues.emplace_back(&Op, SourceReg); | |||
294 | } | |||
295 | } | |||
296 | } | |||
297 | ||||
298 | bool AliasingRegisterOperands::hasImplicitAliasing() const { | |||
299 | const auto HasImplicit = [](const RegisterOperandAssignment &ROV) { | |||
300 | return ROV.Op->isImplicit(); | |||
301 | }; | |||
302 | return llvm::any_of(Defs, HasImplicit) && llvm::any_of(Uses, HasImplicit); | |||
303 | } | |||
304 | ||||
305 | bool AliasingConfigurations::empty() const { return Configurations.empty(); } | |||
306 | ||||
307 | bool AliasingConfigurations::hasImplicitAliasing() const { | |||
308 | return llvm::any_of(Configurations, [](const AliasingRegisterOperands &ARO) { | |||
309 | return ARO.hasImplicitAliasing(); | |||
310 | }); | |||
311 | } | |||
312 | ||||
313 | AliasingConfigurations::AliasingConfigurations( | |||
314 | const Instruction &DefInstruction, const Instruction &UseInstruction) { | |||
315 | if (UseInstruction.AllUseRegs.anyCommon(DefInstruction.AllDefRegs)) { | |||
316 | auto CommonRegisters = UseInstruction.AllUseRegs; | |||
317 | CommonRegisters &= DefInstruction.AllDefRegs; | |||
318 | for (const llvm::MCPhysReg Reg : CommonRegisters.set_bits()) { | |||
319 | AliasingRegisterOperands ARO; | |||
320 | addOperandIfAlias(Reg, true, DefInstruction.Operands, ARO.Defs); | |||
321 | addOperandIfAlias(Reg, false, UseInstruction.Operands, ARO.Uses); | |||
322 | if (!ARO.Defs.empty() && !ARO.Uses.empty() && | |||
323 | !llvm::is_contained(Configurations, ARO)) | |||
324 | Configurations.push_back(std::move(ARO)); | |||
325 | } | |||
326 | } | |||
327 | } | |||
328 | ||||
329 | void DumpMCOperand(const llvm::MCRegisterInfo &MCRegisterInfo, | |||
330 | const llvm::MCOperand &Op, llvm::raw_ostream &OS) { | |||
331 | if (!Op.isValid()) | |||
332 | OS << "Invalid"; | |||
333 | else if (Op.isReg()) | |||
334 | OS << MCRegisterInfo.getName(Op.getReg()); | |||
335 | else if (Op.isImm()) | |||
336 | OS << Op.getImm(); | |||
337 | else if (Op.isFPImm()) | |||
338 | OS << Op.getFPImm(); | |||
339 | else if (Op.isExpr()) | |||
340 | OS << "Expr"; | |||
341 | else if (Op.isInst()) | |||
342 | OS << "SubInst"; | |||
343 | } | |||
344 | ||||
345 | void DumpMCInst(const llvm::MCRegisterInfo &MCRegisterInfo, | |||
346 | const llvm::MCInstrInfo &MCInstrInfo, | |||
347 | const llvm::MCInst &MCInst, llvm::raw_ostream &OS) { | |||
348 | OS << MCInstrInfo.getName(MCInst.getOpcode()); | |||
349 | for (unsigned I = 0, E = MCInst.getNumOperands(); I < E; ++I) { | |||
350 | if (I > 0) | |||
351 | OS << ','; | |||
352 | OS << ' '; | |||
353 | DumpMCOperand(MCRegisterInfo, MCInst.getOperand(I), OS); | |||
354 | } | |||
355 | } | |||
356 | ||||
357 | } // namespace exegesis | |||
358 | } // namespace llvm |