blob: 2f09bc1b0eba79e8690ef60e3e884a601e4b463a [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
Clement Courbet0e69e2d2018-05-17 10:52:18 +000090Instruction::Instruction(const llvm::MCInstrDesc &MCInstrDesc,
Guillaume Chateletc9f727b2018-06-13 13:24:41 +000091 const RegisterAliasingTrackerCache &RATC)
Guillaume Chateletef6cef52018-06-20 08:52:30 +000092 : Description(&MCInstrDesc) {
Clement Courbet0e69e2d2018-05-17 10:52:18 +000093 unsigned OpIndex = 0;
94 for (; OpIndex < MCInstrDesc.getNumOperands(); ++OpIndex) {
95 const auto &OpInfo = MCInstrDesc.opInfo_begin()[OpIndex];
96 Operand Operand;
97 Operand.Index = OpIndex;
98 Operand.IsDef = (OpIndex < MCInstrDesc.getNumDefs());
Clement Courbet0e69e2d2018-05-17 10:52:18 +000099 // TODO(gchatelet): Handle isLookupPtrRegClass.
100 if (OpInfo.RegClass >= 0)
101 Operand.Tracker = &RATC.getRegisterClass(OpInfo.RegClass);
Guillaume Chateletc9f727b2018-06-13 13:24:41 +0000102 Operand.TiedToIndex =
103 MCInstrDesc.getOperandConstraint(OpIndex, llvm::MCOI::TIED_TO);
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000104 Operand.Info = &OpInfo;
105 Operands.push_back(Operand);
106 }
107 for (const llvm::MCPhysReg *MCPhysReg = MCInstrDesc.getImplicitDefs();
108 MCPhysReg && *MCPhysReg; ++MCPhysReg, ++OpIndex) {
109 Operand Operand;
110 Operand.Index = OpIndex;
111 Operand.IsDef = true;
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000112 Operand.Tracker = &RATC.getRegister(*MCPhysReg);
113 Operand.ImplicitReg = MCPhysReg;
114 Operands.push_back(Operand);
115 }
116 for (const llvm::MCPhysReg *MCPhysReg = MCInstrDesc.getImplicitUses();
117 MCPhysReg && *MCPhysReg; ++MCPhysReg, ++OpIndex) {
118 Operand Operand;
119 Operand.Index = OpIndex;
120 Operand.IsDef = false;
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000121 Operand.Tracker = &RATC.getRegister(*MCPhysReg);
122 Operand.ImplicitReg = MCPhysReg;
123 Operands.push_back(Operand);
124 }
Guillaume Chateletc9f727b2018-06-13 13:24:41 +0000125 // Assigning Variables to non tied explicit operands.
126 Variables.reserve(Operands.size()); // Variables.size() <= Operands.size()
127 for (auto &Op : Operands)
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000128 if (Op.isExplicit() && !Op.isTied()) {
Guillaume Chateletc9f727b2018-06-13 13:24:41 +0000129 const size_t VariableIndex = Variables.size();
130 Op.VariableIndex = VariableIndex;
131 Variables.emplace_back();
132 Variables.back().Index = VariableIndex;
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000133 }
Guillaume Chateletc9f727b2018-06-13 13:24:41 +0000134 // Assigning Variables to tied operands.
135 for (auto &Op : Operands)
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000136 if (Op.isTied())
137 Op.VariableIndex = Operands[Op.getTiedToIndex()].getVariableIndex();
Guillaume Chateletc9f727b2018-06-13 13:24:41 +0000138 // Assigning Operands to Variables.
139 for (auto &Op : Operands)
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000140 if (Op.isVariable())
141 Variables[Op.getVariableIndex()].TiedOperands.push_back(Op.getIndex());
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000142 // Processing Aliasing.
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000143 ImplDefRegs = RATC.emptyRegisters();
144 ImplUseRegs = RATC.emptyRegisters();
145 AllDefRegs = RATC.emptyRegisters();
146 AllUseRegs = RATC.emptyRegisters();
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000147 for (const auto &Op : Operands) {
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000148 if (Op.isReg()) {
149 const auto &AliasingBits = Op.getRegisterAliasing().aliasedBits();
150 if (Op.isDef())
151 AllDefRegs |= AliasingBits;
152 if (Op.isUse())
153 AllUseRegs |= AliasingBits;
154 if (Op.isDef() && Op.isImplicit())
155 ImplDefRegs |= AliasingBits;
156 if (Op.isUse() && Op.isImplicit())
157 ImplUseRegs |= AliasingBits;
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000158 }
159 }
160}
161
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000162const Operand &Instruction::getPrimaryOperand(const Variable &Var) const {
163 const auto PrimaryOperandIndex = Var.getPrimaryOperandIndex();
164 assert(PrimaryOperandIndex < Operands.size());
165 return Operands[PrimaryOperandIndex];
166}
167
Guillaume Chateletfb943542018-08-01 14:41:45 +0000168bool Instruction::hasMemoryOperands() const {
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000169 return std::any_of(Operands.begin(), Operands.end(), [](const Operand &Op) {
170 return Op.isReg() && Op.isExplicit() && Op.isMemory();
171 });
172}
173
174bool Instruction::hasAliasingImplicitRegisters() const {
175 return ImplDefRegs.anyCommon(ImplUseRegs);
176}
177
178bool Instruction::hasTiedRegisters() const {
179 return llvm::any_of(
Guillaume Chateletcf6d5fa2018-10-09 09:33:29 +0000180 Variables, [](const Variable &Var) { return Var.hasTiedOperands(); });
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000181}
182
183bool Instruction::hasAliasingRegisters() const {
184 return AllDefRegs.anyCommon(AllUseRegs);
Guillaume Chateletfb943542018-08-01 14:41:45 +0000185}
186
Guillaume Chatelet22cccff2018-10-09 14:51:33 +0000187void Instruction::dump(const llvm::MCRegisterInfo &RegInfo,
Guillaume Chatelet547d2dd2018-10-09 14:51:29 +0000188 llvm::raw_ostream &Stream) const {
189 for (const auto &Op : Operands) {
190 Stream << "- Op" << Op.getIndex();
191 if (Op.isExplicit())
192 Stream << " Explicit";
193 if (Op.isImplicit())
194 Stream << " Implicit";
195 if (Op.isUse())
196 Stream << " Use";
197 if (Op.isDef())
198 Stream << " Def";
199 if (Op.isImmediate())
200 Stream << " Immediate";
201 if (Op.isMemory())
202 Stream << " Memory";
203 if (Op.isReg()) {
204 if (Op.isImplicitReg())
205 Stream << " Reg(" << RegInfo.getName(Op.getImplicitReg()) << ")";
206 else
207 Stream << " RegClass("
208 << RegInfo.getRegClassName(
209 &RegInfo.getRegClass(Op.Info->RegClass))
210 << ")";
211 }
212 if (Op.isTied())
213 Stream << " TiedToOp" << Op.getTiedToIndex();
214 Stream << "\n";
215 }
216 for (const auto &Var : Variables) {
217 Stream << "- Var" << Var.getIndex();
218 for (auto OperandIndex : Var.TiedOperands)
219 Stream << " Op" << OperandIndex;
220 Stream << "\n";
221 }
222 if (hasMemoryOperands())
223 Stream << "- hasMemoryOperands\n";
224 if (hasAliasingImplicitRegisters())
225 Stream << "- hasAliasingImplicitRegisters (execution is always serial)\n";
226 if (hasTiedRegisters())
227 Stream << "- hasTiedRegisters (execution is always serial)\n";
228 if (hasAliasingRegisters())
229 Stream << "- hasAliasingRegisters\n";
230}
231
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000232bool RegisterOperandAssignment::
233operator==(const RegisterOperandAssignment &Other) const {
234 return std::tie(Op, Reg) == std::tie(Other.Op, Other.Reg);
235}
236
237bool AliasingRegisterOperands::
238operator==(const AliasingRegisterOperands &Other) const {
239 return std::tie(Defs, Uses) == std::tie(Other.Defs, Other.Uses);
240}
241
242static void addOperandIfAlias(
243 const llvm::MCPhysReg Reg, bool SelectDef, llvm::ArrayRef<Operand> Operands,
244 llvm::SmallVectorImpl<RegisterOperandAssignment> &OperandValues) {
245 for (const auto &Op : Operands) {
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000246 if (Op.isReg() && Op.isDef() == SelectDef) {
247 const int SourceReg = Op.getRegisterAliasing().getOrigin(Reg);
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000248 if (SourceReg >= 0)
249 OperandValues.emplace_back(&Op, SourceReg);
250 }
251 }
252}
253
254bool AliasingRegisterOperands::hasImplicitAliasing() const {
255 const auto HasImplicit = [](const RegisterOperandAssignment &ROV) {
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000256 return ROV.Op->isImplicit();
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000257 };
258 return llvm::any_of(Defs, HasImplicit) && llvm::any_of(Uses, HasImplicit);
259}
260
261bool AliasingConfigurations::empty() const { return Configurations.empty(); }
262
263bool AliasingConfigurations::hasImplicitAliasing() const {
264 return llvm::any_of(Configurations, [](const AliasingRegisterOperands &ARO) {
265 return ARO.hasImplicitAliasing();
266 });
267}
268
269AliasingConfigurations::AliasingConfigurations(
270 const Instruction &DefInstruction, const Instruction &UseInstruction)
271 : DefInstruction(DefInstruction), UseInstruction(UseInstruction) {
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000272 if (UseInstruction.AllUseRegs.anyCommon(DefInstruction.AllDefRegs)) {
273 auto CommonRegisters = UseInstruction.AllUseRegs;
274 CommonRegisters &= DefInstruction.AllDefRegs;
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000275 for (const llvm::MCPhysReg Reg : CommonRegisters.set_bits()) {
276 AliasingRegisterOperands ARO;
277 addOperandIfAlias(Reg, true, DefInstruction.Operands, ARO.Defs);
278 addOperandIfAlias(Reg, false, UseInstruction.Operands, ARO.Uses);
279 if (!ARO.Defs.empty() && !ARO.Uses.empty() &&
280 !llvm::is_contained(Configurations, ARO))
281 Configurations.push_back(std::move(ARO));
282 }
283 }
284}
285
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000286void DumpMCOperand(const llvm::MCRegisterInfo &MCRegisterInfo,
287 const llvm::MCOperand &Op, llvm::raw_ostream &OS) {
288 if (!Op.isValid())
289 OS << "Invalid";
290 else if (Op.isReg())
291 OS << MCRegisterInfo.getName(Op.getReg());
292 else if (Op.isImm())
293 OS << Op.getImm();
294 else if (Op.isFPImm())
295 OS << Op.getFPImm();
296 else if (Op.isExpr())
297 OS << "Expr";
298 else if (Op.isInst())
299 OS << "SubInst";
300}
301
302void DumpMCInst(const llvm::MCRegisterInfo &MCRegisterInfo,
303 const llvm::MCInstrInfo &MCInstrInfo,
304 const llvm::MCInst &MCInst, llvm::raw_ostream &OS) {
305 OS << MCInstrInfo.getName(MCInst.getOpcode());
306 for (unsigned I = 0, E = MCInst.getNumOperands(); I < E; ++I) {
307 if (I > 0)
308 OS << ',';
309 OS << ' ';
310 DumpMCOperand(MCRegisterInfo, MCInst.getOperand(I), OS);
311 }
312}
313
314} // namespace exegesis