blob: 75d85873146a30eb7b8419728d99f20306746183 [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
Guillaume Chatelet0c17cbf2018-10-10 09:12:36 +0000178bool Instruction::hasAliasingImplicitRegistersThrough(
179 const Instruction &OtherInstr) const {
180 return ImplDefRegs.anyCommon(OtherInstr.ImplUseRegs) &&
181 OtherInstr.ImplDefRegs.anyCommon(ImplUseRegs);
182}
183
184bool Instruction::hasAliasingRegistersThrough(
185 const Instruction &OtherInstr) const {
186 return AllDefRegs.anyCommon(OtherInstr.AllUseRegs) &&
187 OtherInstr.AllDefRegs.anyCommon(AllUseRegs);
188}
189
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000190bool Instruction::hasTiedRegisters() const {
191 return llvm::any_of(
Guillaume Chateletcf6d5fa2018-10-09 09:33:29 +0000192 Variables, [](const Variable &Var) { return Var.hasTiedOperands(); });
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000193}
194
195bool Instruction::hasAliasingRegisters() const {
196 return AllDefRegs.anyCommon(AllUseRegs);
Guillaume Chateletfb943542018-08-01 14:41:45 +0000197}
198
Guillaume Chatelet22cccff2018-10-09 14:51:33 +0000199void Instruction::dump(const llvm::MCRegisterInfo &RegInfo,
Guillaume Chatelet547d2dd2018-10-09 14:51:29 +0000200 llvm::raw_ostream &Stream) const {
201 for (const auto &Op : Operands) {
202 Stream << "- Op" << Op.getIndex();
203 if (Op.isExplicit())
204 Stream << " Explicit";
205 if (Op.isImplicit())
206 Stream << " Implicit";
207 if (Op.isUse())
208 Stream << " Use";
209 if (Op.isDef())
210 Stream << " Def";
211 if (Op.isImmediate())
212 Stream << " Immediate";
213 if (Op.isMemory())
214 Stream << " Memory";
215 if (Op.isReg()) {
216 if (Op.isImplicitReg())
217 Stream << " Reg(" << RegInfo.getName(Op.getImplicitReg()) << ")";
218 else
219 Stream << " RegClass("
220 << RegInfo.getRegClassName(
221 &RegInfo.getRegClass(Op.Info->RegClass))
222 << ")";
223 }
224 if (Op.isTied())
225 Stream << " TiedToOp" << Op.getTiedToIndex();
226 Stream << "\n";
227 }
228 for (const auto &Var : Variables) {
229 Stream << "- Var" << Var.getIndex();
Guillaume Chatelet0c17cbf2018-10-10 09:12:36 +0000230 Stream << " (";
Guillaume Chatelet547d2dd2018-10-09 14:51:29 +0000231 for (auto OperandIndex : Var.TiedOperands)
Guillaume Chatelet0c17cbf2018-10-10 09:12:36 +0000232 Stream << "Op" << OperandIndex;
233 Stream << ")";
Guillaume Chatelet547d2dd2018-10-09 14:51:29 +0000234 Stream << "\n";
235 }
236 if (hasMemoryOperands())
237 Stream << "- hasMemoryOperands\n";
238 if (hasAliasingImplicitRegisters())
239 Stream << "- hasAliasingImplicitRegisters (execution is always serial)\n";
240 if (hasTiedRegisters())
241 Stream << "- hasTiedRegisters (execution is always serial)\n";
242 if (hasAliasingRegisters())
243 Stream << "- hasAliasingRegisters\n";
244}
245
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000246bool RegisterOperandAssignment::
247operator==(const RegisterOperandAssignment &Other) const {
248 return std::tie(Op, Reg) == std::tie(Other.Op, Other.Reg);
249}
250
251bool AliasingRegisterOperands::
252operator==(const AliasingRegisterOperands &Other) const {
253 return std::tie(Defs, Uses) == std::tie(Other.Defs, Other.Uses);
254}
255
256static void addOperandIfAlias(
257 const llvm::MCPhysReg Reg, bool SelectDef, llvm::ArrayRef<Operand> Operands,
258 llvm::SmallVectorImpl<RegisterOperandAssignment> &OperandValues) {
259 for (const auto &Op : Operands) {
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000260 if (Op.isReg() && Op.isDef() == SelectDef) {
261 const int SourceReg = Op.getRegisterAliasing().getOrigin(Reg);
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000262 if (SourceReg >= 0)
263 OperandValues.emplace_back(&Op, SourceReg);
264 }
265 }
266}
267
268bool AliasingRegisterOperands::hasImplicitAliasing() const {
269 const auto HasImplicit = [](const RegisterOperandAssignment &ROV) {
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000270 return ROV.Op->isImplicit();
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000271 };
272 return llvm::any_of(Defs, HasImplicit) && llvm::any_of(Uses, HasImplicit);
273}
274
275bool AliasingConfigurations::empty() const { return Configurations.empty(); }
276
277bool AliasingConfigurations::hasImplicitAliasing() const {
278 return llvm::any_of(Configurations, [](const AliasingRegisterOperands &ARO) {
279 return ARO.hasImplicitAliasing();
280 });
281}
282
283AliasingConfigurations::AliasingConfigurations(
284 const Instruction &DefInstruction, const Instruction &UseInstruction)
285 : DefInstruction(DefInstruction), UseInstruction(UseInstruction) {
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000286 if (UseInstruction.AllUseRegs.anyCommon(DefInstruction.AllDefRegs)) {
287 auto CommonRegisters = UseInstruction.AllUseRegs;
288 CommonRegisters &= DefInstruction.AllDefRegs;
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000289 for (const llvm::MCPhysReg Reg : CommonRegisters.set_bits()) {
290 AliasingRegisterOperands ARO;
291 addOperandIfAlias(Reg, true, DefInstruction.Operands, ARO.Defs);
292 addOperandIfAlias(Reg, false, UseInstruction.Operands, ARO.Uses);
293 if (!ARO.Defs.empty() && !ARO.Uses.empty() &&
294 !llvm::is_contained(Configurations, ARO))
295 Configurations.push_back(std::move(ARO));
296 }
297 }
298}
299
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000300void DumpMCOperand(const llvm::MCRegisterInfo &MCRegisterInfo,
301 const llvm::MCOperand &Op, llvm::raw_ostream &OS) {
302 if (!Op.isValid())
303 OS << "Invalid";
304 else if (Op.isReg())
305 OS << MCRegisterInfo.getName(Op.getReg());
306 else if (Op.isImm())
307 OS << Op.getImm();
308 else if (Op.isFPImm())
309 OS << Op.getFPImm();
310 else if (Op.isExpr())
311 OS << "Expr";
312 else if (Op.isInst())
313 OS << "SubInst";
314}
315
316void DumpMCInst(const llvm::MCRegisterInfo &MCRegisterInfo,
317 const llvm::MCInstrInfo &MCInstrInfo,
318 const llvm::MCInst &MCInst, llvm::raw_ostream &OS) {
319 OS << MCInstrInfo.getName(MCInst.getOpcode());
320 for (unsigned I = 0, E = MCInst.getNumOperands(); I < E; ++I) {
321 if (I > 0)
322 OS << ',';
323 OS << ' ';
324 DumpMCOperand(MCRegisterInfo, MCInst.getOperand(I), OS);
325 }
326}
327
328} // namespace exegesis