blob: fa9378856f48ad4d791440e7faf89d33595a7f0b [file] [log] [blame]
Clement Courbet0e69e2d2018-05-17 10:52:18 +00001//===-- 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
18namespace exegesis {
19
Guillaume Chatelet09c28392018-10-09 08:59:10 +000020unsigned Variable::getIndex() const {
Guillaume Chateletfe5b0b42018-10-09 10:06:19 +000021 assert(Index >= 0 && "Index must be set");
Guillaume Chatelet09c28392018-10-09 08:59:10 +000022 return Index;
23}
Guillaume Chateletfe5b0b42018-10-09 10:06:19 +000024
Guillaume Chatelet09c28392018-10-09 08:59:10 +000025unsigned Variable::getPrimaryOperandIndex() const {
26 assert(!TiedOperands.empty());
27 return TiedOperands[0];
28}
29
30bool Variable::hasTiedOperands() const { return TiedOperands.size() > 1; }
31
Guillaume Chatelet547d2dd2018-10-09 14:51:29 +000032unsigned Operand::getIndex() const {
33 assert(Index >= 0 && "Index must be set");
34 return Index;
35}
Guillaume Chatelet09c28392018-10-09 08:59:10 +000036
37bool Operand::isExplicit() const { return Info; }
38
39bool Operand::isImplicit() const { return !Info; }
40
41bool Operand::isImplicitReg() const { return ImplicitReg; }
42
43bool Operand::isDef() const { return IsDef; }
44
45bool Operand::isUse() const { return !IsDef; }
46
47bool Operand::isReg() const { return Tracker; }
48
49bool Operand::isTied() const { return TiedToIndex >= 0; }
50
51bool Operand::isVariable() const { return VariableIndex >= 0; }
52
53bool Operand::isMemory() const {
54 return isExplicit() &&
55 getExplicitOperandInfo().OperandType == llvm::MCOI::OPERAND_MEMORY;
56}
57
58bool Operand::isImmediate() const {
59 return isExplicit() &&
60 getExplicitOperandInfo().OperandType == llvm::MCOI::OPERAND_IMMEDIATE;
61}
62
Guillaume Chatelet547d2dd2018-10-09 14:51:29 +000063unsigned Operand::getTiedToIndex() const {
64 assert(isTied() && "Operand must be tied to get the tied index");
65 assert(TiedToIndex >= 0 && "TiedToIndex must be set");
Guillaume Chatelet09c28392018-10-09 08:59:10 +000066 return TiedToIndex;
67}
68
Guillaume Chatelet547d2dd2018-10-09 14:51:29 +000069unsigned Operand::getVariableIndex() const {
70 assert(isVariable() && "Operand must be variable to get the Variable index");
71 assert(VariableIndex >= 0 && "VariableIndex must be set");
Guillaume Chatelet09c28392018-10-09 08:59:10 +000072 return VariableIndex;
73}
74
75unsigned Operand::getImplicitReg() const {
76 assert(ImplicitReg);
77 return *ImplicitReg;
78}
79
80const RegisterAliasingTracker &Operand::getRegisterAliasing() const {
81 assert(Tracker);
82 return *Tracker;
83}
84
85const llvm::MCOperandInfo &Operand::getExplicitOperandInfo() const {
86 assert(Info);
87 return *Info;
88}
89
Guillaume Chateletee9c2a172018-10-10 14:22:48 +000090Instruction::Instruction(const LLVMState &State, unsigned Opcode)
Guillaume Chatelet9b592382018-10-10 14:57:32 +000091 : Description(&State.getInstrInfo().get(Opcode)),
92 Name(State.getInstrInfo().getName(Opcode)) {
Guillaume Chateletee9c2a172018-10-10 14:22:48 +000093 const auto &RATC = State.getRATC();
Clement Courbet0e69e2d2018-05-17 10:52:18 +000094 unsigned OpIndex = 0;
Guillaume Chateletee9c2a172018-10-10 14:22:48 +000095 for (; OpIndex < Description->getNumOperands(); ++OpIndex) {
96 const auto &OpInfo = Description->opInfo_begin()[OpIndex];
Clement Courbet0e69e2d2018-05-17 10:52:18 +000097 Operand Operand;
98 Operand.Index = OpIndex;
Guillaume Chateletee9c2a172018-10-10 14:22:48 +000099 Operand.IsDef = (OpIndex < Description->getNumDefs());
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000100 // TODO(gchatelet): Handle isLookupPtrRegClass.
101 if (OpInfo.RegClass >= 0)
102 Operand.Tracker = &RATC.getRegisterClass(OpInfo.RegClass);
Guillaume Chateletc9f727b2018-06-13 13:24:41 +0000103 Operand.TiedToIndex =
Guillaume Chateletee9c2a172018-10-10 14:22:48 +0000104 Description->getOperandConstraint(OpIndex, llvm::MCOI::TIED_TO);
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000105 Operand.Info = &OpInfo;
106 Operands.push_back(Operand);
107 }
Guillaume Chateletee9c2a172018-10-10 14:22:48 +0000108 for (const llvm::MCPhysReg *MCPhysReg = Description->getImplicitDefs();
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000109 MCPhysReg && *MCPhysReg; ++MCPhysReg, ++OpIndex) {
110 Operand Operand;
111 Operand.Index = OpIndex;
112 Operand.IsDef = true;
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000113 Operand.Tracker = &RATC.getRegister(*MCPhysReg);
114 Operand.ImplicitReg = MCPhysReg;
115 Operands.push_back(Operand);
116 }
Guillaume Chateletee9c2a172018-10-10 14:22:48 +0000117 for (const llvm::MCPhysReg *MCPhysReg = Description->getImplicitUses();
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000118 MCPhysReg && *MCPhysReg; ++MCPhysReg, ++OpIndex) {
119 Operand Operand;
120 Operand.Index = OpIndex;
121 Operand.IsDef = false;
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000122 Operand.Tracker = &RATC.getRegister(*MCPhysReg);
123 Operand.ImplicitReg = MCPhysReg;
124 Operands.push_back(Operand);
125 }
Guillaume Chateletc9f727b2018-06-13 13:24:41 +0000126 // Assigning Variables to non tied explicit operands.
127 Variables.reserve(Operands.size()); // Variables.size() <= Operands.size()
128 for (auto &Op : Operands)
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000129 if (Op.isExplicit() && !Op.isTied()) {
Guillaume Chateletc9f727b2018-06-13 13:24:41 +0000130 const size_t VariableIndex = Variables.size();
131 Op.VariableIndex = VariableIndex;
132 Variables.emplace_back();
133 Variables.back().Index = VariableIndex;
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000134 }
Guillaume Chateletc9f727b2018-06-13 13:24:41 +0000135 // Assigning Variables to tied operands.
136 for (auto &Op : Operands)
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000137 if (Op.isTied())
138 Op.VariableIndex = Operands[Op.getTiedToIndex()].getVariableIndex();
Guillaume Chateletc9f727b2018-06-13 13:24:41 +0000139 // Assigning Operands to Variables.
140 for (auto &Op : Operands)
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000141 if (Op.isVariable())
142 Variables[Op.getVariableIndex()].TiedOperands.push_back(Op.getIndex());
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000143 // Processing Aliasing.
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000144 ImplDefRegs = RATC.emptyRegisters();
145 ImplUseRegs = RATC.emptyRegisters();
146 AllDefRegs = RATC.emptyRegisters();
147 AllUseRegs = RATC.emptyRegisters();
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000148 for (const auto &Op : Operands) {
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000149 if (Op.isReg()) {
150 const auto &AliasingBits = Op.getRegisterAliasing().aliasedBits();
151 if (Op.isDef())
152 AllDefRegs |= AliasingBits;
153 if (Op.isUse())
154 AllUseRegs |= AliasingBits;
155 if (Op.isDef() && Op.isImplicit())
156 ImplDefRegs |= AliasingBits;
157 if (Op.isUse() && Op.isImplicit())
158 ImplUseRegs |= AliasingBits;
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000159 }
160 }
161}
162
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000163const Operand &Instruction::getPrimaryOperand(const Variable &Var) const {
164 const auto PrimaryOperandIndex = Var.getPrimaryOperandIndex();
165 assert(PrimaryOperandIndex < Operands.size());
166 return Operands[PrimaryOperandIndex];
167}
168
Guillaume Chateletfb943542018-08-01 14:41:45 +0000169bool Instruction::hasMemoryOperands() const {
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000170 return std::any_of(Operands.begin(), Operands.end(), [](const Operand &Op) {
171 return Op.isReg() && Op.isExplicit() && Op.isMemory();
172 });
173}
174
175bool Instruction::hasAliasingImplicitRegisters() const {
176 return ImplDefRegs.anyCommon(ImplUseRegs);
177}
178
Guillaume Chatelet0c17cbf2018-10-10 09:12:36 +0000179bool Instruction::hasAliasingImplicitRegistersThrough(
180 const Instruction &OtherInstr) const {
181 return ImplDefRegs.anyCommon(OtherInstr.ImplUseRegs) &&
182 OtherInstr.ImplDefRegs.anyCommon(ImplUseRegs);
183}
184
185bool Instruction::hasAliasingRegistersThrough(
186 const Instruction &OtherInstr) const {
187 return AllDefRegs.anyCommon(OtherInstr.AllUseRegs) &&
188 OtherInstr.AllDefRegs.anyCommon(AllUseRegs);
189}
190
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000191bool Instruction::hasTiedRegisters() const {
192 return llvm::any_of(
Guillaume Chateletcf6d5fa2018-10-09 09:33:29 +0000193 Variables, [](const Variable &Var) { return Var.hasTiedOperands(); });
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000194}
195
196bool Instruction::hasAliasingRegisters() const {
197 return AllDefRegs.anyCommon(AllUseRegs);
Guillaume Chateletfb943542018-08-01 14:41:45 +0000198}
199
Guillaume Chatelet22cccff2018-10-09 14:51:33 +0000200void Instruction::dump(const llvm::MCRegisterInfo &RegInfo,
Guillaume Chatelet547d2dd2018-10-09 14:51:29 +0000201 llvm::raw_ostream &Stream) const {
Guillaume Chatelet9b592382018-10-10 14:57:32 +0000202 Stream << "- " << Name << "\n";
Guillaume Chatelet547d2dd2018-10-09 14:51:29 +0000203 for (const auto &Op : Operands) {
204 Stream << "- Op" << Op.getIndex();
205 if (Op.isExplicit())
206 Stream << " Explicit";
207 if (Op.isImplicit())
208 Stream << " Implicit";
209 if (Op.isUse())
210 Stream << " Use";
211 if (Op.isDef())
212 Stream << " Def";
213 if (Op.isImmediate())
214 Stream << " Immediate";
215 if (Op.isMemory())
216 Stream << " Memory";
217 if (Op.isReg()) {
218 if (Op.isImplicitReg())
219 Stream << " Reg(" << RegInfo.getName(Op.getImplicitReg()) << ")";
220 else
221 Stream << " RegClass("
222 << RegInfo.getRegClassName(
223 &RegInfo.getRegClass(Op.Info->RegClass))
224 << ")";
225 }
226 if (Op.isTied())
227 Stream << " TiedToOp" << Op.getTiedToIndex();
228 Stream << "\n";
229 }
230 for (const auto &Var : Variables) {
231 Stream << "- Var" << Var.getIndex();
Guillaume Chatelet9b592382018-10-10 14:57:32 +0000232 Stream << " [";
233 bool IsFirst = true;
234 for (auto OperandIndex : Var.TiedOperands) {
235 if (!IsFirst)
236 Stream << ",";
Guillaume Chatelet0c17cbf2018-10-10 09:12:36 +0000237 Stream << "Op" << OperandIndex;
Guillaume Chatelet9b592382018-10-10 14:57:32 +0000238 IsFirst = false;
239 }
240 Stream << "]";
Guillaume Chatelet547d2dd2018-10-09 14:51:29 +0000241 Stream << "\n";
242 }
243 if (hasMemoryOperands())
244 Stream << "- hasMemoryOperands\n";
245 if (hasAliasingImplicitRegisters())
246 Stream << "- hasAliasingImplicitRegisters (execution is always serial)\n";
247 if (hasTiedRegisters())
248 Stream << "- hasTiedRegisters (execution is always serial)\n";
249 if (hasAliasingRegisters())
250 Stream << "- hasAliasingRegisters\n";
251}
252
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000253bool RegisterOperandAssignment::
254operator==(const RegisterOperandAssignment &Other) const {
255 return std::tie(Op, Reg) == std::tie(Other.Op, Other.Reg);
256}
257
258bool AliasingRegisterOperands::
259operator==(const AliasingRegisterOperands &Other) const {
260 return std::tie(Defs, Uses) == std::tie(Other.Defs, Other.Uses);
261}
262
263static void addOperandIfAlias(
264 const llvm::MCPhysReg Reg, bool SelectDef, llvm::ArrayRef<Operand> Operands,
265 llvm::SmallVectorImpl<RegisterOperandAssignment> &OperandValues) {
266 for (const auto &Op : Operands) {
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000267 if (Op.isReg() && Op.isDef() == SelectDef) {
268 const int SourceReg = Op.getRegisterAliasing().getOrigin(Reg);
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000269 if (SourceReg >= 0)
270 OperandValues.emplace_back(&Op, SourceReg);
271 }
272 }
273}
274
275bool AliasingRegisterOperands::hasImplicitAliasing() const {
276 const auto HasImplicit = [](const RegisterOperandAssignment &ROV) {
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000277 return ROV.Op->isImplicit();
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000278 };
279 return llvm::any_of(Defs, HasImplicit) && llvm::any_of(Uses, HasImplicit);
280}
281
282bool AliasingConfigurations::empty() const { return Configurations.empty(); }
283
284bool AliasingConfigurations::hasImplicitAliasing() const {
285 return llvm::any_of(Configurations, [](const AliasingRegisterOperands &ARO) {
286 return ARO.hasImplicitAliasing();
287 });
288}
289
290AliasingConfigurations::AliasingConfigurations(
291 const Instruction &DefInstruction, const Instruction &UseInstruction)
292 : DefInstruction(DefInstruction), UseInstruction(UseInstruction) {
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000293 if (UseInstruction.AllUseRegs.anyCommon(DefInstruction.AllDefRegs)) {
294 auto CommonRegisters = UseInstruction.AllUseRegs;
295 CommonRegisters &= DefInstruction.AllDefRegs;
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000296 for (const llvm::MCPhysReg Reg : CommonRegisters.set_bits()) {
297 AliasingRegisterOperands ARO;
298 addOperandIfAlias(Reg, true, DefInstruction.Operands, ARO.Defs);
299 addOperandIfAlias(Reg, false, UseInstruction.Operands, ARO.Uses);
300 if (!ARO.Defs.empty() && !ARO.Uses.empty() &&
301 !llvm::is_contained(Configurations, ARO))
302 Configurations.push_back(std::move(ARO));
303 }
304 }
305}
306
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000307void DumpMCOperand(const llvm::MCRegisterInfo &MCRegisterInfo,
308 const llvm::MCOperand &Op, llvm::raw_ostream &OS) {
309 if (!Op.isValid())
310 OS << "Invalid";
311 else if (Op.isReg())
312 OS << MCRegisterInfo.getName(Op.getReg());
313 else if (Op.isImm())
314 OS << Op.getImm();
315 else if (Op.isFPImm())
316 OS << Op.getFPImm();
317 else if (Op.isExpr())
318 OS << "Expr";
319 else if (Op.isInst())
320 OS << "SubInst";
321}
322
323void DumpMCInst(const llvm::MCRegisterInfo &MCRegisterInfo,
324 const llvm::MCInstrInfo &MCInstrInfo,
325 const llvm::MCInst &MCInst, llvm::raw_ostream &OS) {
326 OS << MCInstrInfo.getName(MCInst.getOpcode());
327 for (unsigned I = 0, E = MCInst.getNumOperands(); I < E; ++I) {
328 if (I > 0)
329 OS << ',';
330 OS << ' ';
331 DumpMCOperand(MCRegisterInfo, MCInst.getOperand(I), OS);
332 }
333}
334
335} // namespace exegesis