blob: 59f56520efc859738b46ac7b7be21d4fd9729818 [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
Guillaume Chateletfcbb6f32018-10-17 11:37:28 +000030bool Variable::hasTiedOperands() const {
31 assert(TiedOperands.size() <= 2 &&
32 "No more than two operands can be tied together");
33 // By definition only Use and Def operands can be tied together.
34 // TiedOperands[0] is the Def operand (LLVM stores defs first).
35 // TiedOperands[1] is the Use operand.
36 return TiedOperands.size() > 1;
37}
Guillaume Chatelet09c28392018-10-09 08:59:10 +000038
Guillaume Chatelet547d2dd2018-10-09 14:51:29 +000039unsigned Operand::getIndex() const {
40 assert(Index >= 0 && "Index must be set");
41 return Index;
42}
Guillaume Chatelet09c28392018-10-09 08:59:10 +000043
44bool Operand::isExplicit() const { return Info; }
45
46bool Operand::isImplicit() const { return !Info; }
47
48bool Operand::isImplicitReg() const { return ImplicitReg; }
49
50bool Operand::isDef() const { return IsDef; }
51
52bool Operand::isUse() const { return !IsDef; }
53
54bool Operand::isReg() const { return Tracker; }
55
56bool Operand::isTied() const { return TiedToIndex >= 0; }
57
58bool Operand::isVariable() const { return VariableIndex >= 0; }
59
60bool Operand::isMemory() const {
61 return isExplicit() &&
62 getExplicitOperandInfo().OperandType == llvm::MCOI::OPERAND_MEMORY;
63}
64
65bool Operand::isImmediate() const {
66 return isExplicit() &&
67 getExplicitOperandInfo().OperandType == llvm::MCOI::OPERAND_IMMEDIATE;
68}
69
Guillaume Chatelet547d2dd2018-10-09 14:51:29 +000070unsigned Operand::getTiedToIndex() const {
71 assert(isTied() && "Operand must be tied to get the tied index");
72 assert(TiedToIndex >= 0 && "TiedToIndex must be set");
Guillaume Chatelet09c28392018-10-09 08:59:10 +000073 return TiedToIndex;
74}
75
Guillaume Chatelet547d2dd2018-10-09 14:51:29 +000076unsigned Operand::getVariableIndex() const {
77 assert(isVariable() && "Operand must be variable to get the Variable index");
78 assert(VariableIndex >= 0 && "VariableIndex must be set");
Guillaume Chatelet09c28392018-10-09 08:59:10 +000079 return VariableIndex;
80}
81
82unsigned Operand::getImplicitReg() const {
83 assert(ImplicitReg);
84 return *ImplicitReg;
85}
86
87const RegisterAliasingTracker &Operand::getRegisterAliasing() const {
88 assert(Tracker);
89 return *Tracker;
90}
91
92const llvm::MCOperandInfo &Operand::getExplicitOperandInfo() const {
93 assert(Info);
94 return *Info;
95}
96
Guillaume Chateletee9c2a172018-10-10 14:22:48 +000097Instruction::Instruction(const LLVMState &State, unsigned Opcode)
Guillaume Chatelet9b592382018-10-10 14:57:32 +000098 : Description(&State.getInstrInfo().get(Opcode)),
99 Name(State.getInstrInfo().getName(Opcode)) {
Guillaume Chateletee9c2a172018-10-10 14:22:48 +0000100 const auto &RATC = State.getRATC();
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000101 unsigned OpIndex = 0;
Guillaume Chateletee9c2a172018-10-10 14:22:48 +0000102 for (; OpIndex < Description->getNumOperands(); ++OpIndex) {
103 const auto &OpInfo = Description->opInfo_begin()[OpIndex];
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000104 Operand Operand;
105 Operand.Index = OpIndex;
Guillaume Chateletee9c2a172018-10-10 14:22:48 +0000106 Operand.IsDef = (OpIndex < Description->getNumDefs());
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000107 // TODO(gchatelet): Handle isLookupPtrRegClass.
108 if (OpInfo.RegClass >= 0)
109 Operand.Tracker = &RATC.getRegisterClass(OpInfo.RegClass);
Guillaume Chateletc9f727b2018-06-13 13:24:41 +0000110 Operand.TiedToIndex =
Guillaume Chateletee9c2a172018-10-10 14:22:48 +0000111 Description->getOperandConstraint(OpIndex, llvm::MCOI::TIED_TO);
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000112 Operand.Info = &OpInfo;
113 Operands.push_back(Operand);
114 }
Guillaume Chateletee9c2a172018-10-10 14:22:48 +0000115 for (const llvm::MCPhysReg *MCPhysReg = Description->getImplicitDefs();
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000116 MCPhysReg && *MCPhysReg; ++MCPhysReg, ++OpIndex) {
117 Operand Operand;
118 Operand.Index = OpIndex;
119 Operand.IsDef = true;
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000120 Operand.Tracker = &RATC.getRegister(*MCPhysReg);
121 Operand.ImplicitReg = MCPhysReg;
122 Operands.push_back(Operand);
123 }
Guillaume Chateletee9c2a172018-10-10 14:22:48 +0000124 for (const llvm::MCPhysReg *MCPhysReg = Description->getImplicitUses();
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000125 MCPhysReg && *MCPhysReg; ++MCPhysReg, ++OpIndex) {
126 Operand Operand;
127 Operand.Index = OpIndex;
128 Operand.IsDef = false;
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000129 Operand.Tracker = &RATC.getRegister(*MCPhysReg);
130 Operand.ImplicitReg = MCPhysReg;
131 Operands.push_back(Operand);
132 }
Guillaume Chateletc9f727b2018-06-13 13:24:41 +0000133 // Assigning Variables to non tied explicit operands.
134 Variables.reserve(Operands.size()); // Variables.size() <= Operands.size()
135 for (auto &Op : Operands)
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000136 if (Op.isExplicit() && !Op.isTied()) {
Guillaume Chateletc9f727b2018-06-13 13:24:41 +0000137 const size_t VariableIndex = Variables.size();
138 Op.VariableIndex = VariableIndex;
139 Variables.emplace_back();
140 Variables.back().Index = VariableIndex;
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000141 }
Guillaume Chateletc9f727b2018-06-13 13:24:41 +0000142 // Assigning Variables to tied operands.
143 for (auto &Op : Operands)
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000144 if (Op.isTied())
145 Op.VariableIndex = Operands[Op.getTiedToIndex()].getVariableIndex();
Guillaume Chateletc9f727b2018-06-13 13:24:41 +0000146 // Assigning Operands to Variables.
147 for (auto &Op : Operands)
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000148 if (Op.isVariable())
149 Variables[Op.getVariableIndex()].TiedOperands.push_back(Op.getIndex());
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000150 // Processing Aliasing.
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000151 ImplDefRegs = RATC.emptyRegisters();
152 ImplUseRegs = RATC.emptyRegisters();
153 AllDefRegs = RATC.emptyRegisters();
154 AllUseRegs = RATC.emptyRegisters();
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000155 for (const auto &Op : Operands) {
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000156 if (Op.isReg()) {
157 const auto &AliasingBits = Op.getRegisterAliasing().aliasedBits();
158 if (Op.isDef())
159 AllDefRegs |= AliasingBits;
160 if (Op.isUse())
161 AllUseRegs |= AliasingBits;
162 if (Op.isDef() && Op.isImplicit())
163 ImplDefRegs |= AliasingBits;
164 if (Op.isUse() && Op.isImplicit())
165 ImplUseRegs |= AliasingBits;
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000166 }
167 }
168}
169
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000170const Operand &Instruction::getPrimaryOperand(const Variable &Var) const {
171 const auto PrimaryOperandIndex = Var.getPrimaryOperandIndex();
172 assert(PrimaryOperandIndex < Operands.size());
173 return Operands[PrimaryOperandIndex];
174}
175
Guillaume Chateletfb943542018-08-01 14:41:45 +0000176bool Instruction::hasMemoryOperands() const {
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000177 return std::any_of(Operands.begin(), Operands.end(), [](const Operand &Op) {
178 return Op.isReg() && Op.isExplicit() && Op.isMemory();
179 });
180}
181
182bool Instruction::hasAliasingImplicitRegisters() const {
183 return ImplDefRegs.anyCommon(ImplUseRegs);
184}
185
Guillaume Chatelet0c17cbf2018-10-10 09:12:36 +0000186bool Instruction::hasAliasingImplicitRegistersThrough(
187 const Instruction &OtherInstr) const {
188 return ImplDefRegs.anyCommon(OtherInstr.ImplUseRegs) &&
189 OtherInstr.ImplDefRegs.anyCommon(ImplUseRegs);
190}
191
192bool Instruction::hasAliasingRegistersThrough(
193 const Instruction &OtherInstr) const {
194 return AllDefRegs.anyCommon(OtherInstr.AllUseRegs) &&
195 OtherInstr.AllDefRegs.anyCommon(AllUseRegs);
196}
197
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000198bool Instruction::hasTiedRegisters() const {
199 return llvm::any_of(
Guillaume Chateletcf6d5fa2018-10-09 09:33:29 +0000200 Variables, [](const Variable &Var) { return Var.hasTiedOperands(); });
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000201}
202
203bool Instruction::hasAliasingRegisters() const {
204 return AllDefRegs.anyCommon(AllUseRegs);
Guillaume Chateletfb943542018-08-01 14:41:45 +0000205}
206
Guillaume Chateletfcbb6f32018-10-17 11:37:28 +0000207bool Instruction::hasOneUseOrOneDef() const {
208 return AllDefRegs.count() || AllUseRegs.count();
209}
210
Guillaume Chatelet22cccff2018-10-09 14:51:33 +0000211void Instruction::dump(const llvm::MCRegisterInfo &RegInfo,
Guillaume Chatelet547d2dd2018-10-09 14:51:29 +0000212 llvm::raw_ostream &Stream) const {
Guillaume Chatelet9b592382018-10-10 14:57:32 +0000213 Stream << "- " << Name << "\n";
Guillaume Chatelet547d2dd2018-10-09 14:51:29 +0000214 for (const auto &Op : Operands) {
215 Stream << "- Op" << Op.getIndex();
216 if (Op.isExplicit())
217 Stream << " Explicit";
218 if (Op.isImplicit())
219 Stream << " Implicit";
220 if (Op.isUse())
221 Stream << " Use";
222 if (Op.isDef())
223 Stream << " Def";
224 if (Op.isImmediate())
225 Stream << " Immediate";
226 if (Op.isMemory())
227 Stream << " Memory";
228 if (Op.isReg()) {
229 if (Op.isImplicitReg())
230 Stream << " Reg(" << RegInfo.getName(Op.getImplicitReg()) << ")";
231 else
232 Stream << " RegClass("
233 << RegInfo.getRegClassName(
234 &RegInfo.getRegClass(Op.Info->RegClass))
235 << ")";
236 }
237 if (Op.isTied())
238 Stream << " TiedToOp" << Op.getTiedToIndex();
239 Stream << "\n";
240 }
241 for (const auto &Var : Variables) {
242 Stream << "- Var" << Var.getIndex();
Guillaume Chatelet9b592382018-10-10 14:57:32 +0000243 Stream << " [";
244 bool IsFirst = true;
245 for (auto OperandIndex : Var.TiedOperands) {
246 if (!IsFirst)
247 Stream << ",";
Guillaume Chatelet0c17cbf2018-10-10 09:12:36 +0000248 Stream << "Op" << OperandIndex;
Guillaume Chatelet9b592382018-10-10 14:57:32 +0000249 IsFirst = false;
250 }
251 Stream << "]";
Guillaume Chatelet547d2dd2018-10-09 14:51:29 +0000252 Stream << "\n";
253 }
254 if (hasMemoryOperands())
255 Stream << "- hasMemoryOperands\n";
256 if (hasAliasingImplicitRegisters())
257 Stream << "- hasAliasingImplicitRegisters (execution is always serial)\n";
258 if (hasTiedRegisters())
259 Stream << "- hasTiedRegisters (execution is always serial)\n";
260 if (hasAliasingRegisters())
261 Stream << "- hasAliasingRegisters\n";
262}
263
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000264bool RegisterOperandAssignment::
265operator==(const RegisterOperandAssignment &Other) const {
266 return std::tie(Op, Reg) == std::tie(Other.Op, Other.Reg);
267}
268
269bool AliasingRegisterOperands::
270operator==(const AliasingRegisterOperands &Other) const {
271 return std::tie(Defs, Uses) == std::tie(Other.Defs, Other.Uses);
272}
273
274static void addOperandIfAlias(
275 const llvm::MCPhysReg Reg, bool SelectDef, llvm::ArrayRef<Operand> Operands,
276 llvm::SmallVectorImpl<RegisterOperandAssignment> &OperandValues) {
277 for (const auto &Op : Operands) {
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000278 if (Op.isReg() && Op.isDef() == SelectDef) {
279 const int SourceReg = Op.getRegisterAliasing().getOrigin(Reg);
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000280 if (SourceReg >= 0)
281 OperandValues.emplace_back(&Op, SourceReg);
282 }
283 }
284}
285
286bool AliasingRegisterOperands::hasImplicitAliasing() const {
287 const auto HasImplicit = [](const RegisterOperandAssignment &ROV) {
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000288 return ROV.Op->isImplicit();
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000289 };
290 return llvm::any_of(Defs, HasImplicit) && llvm::any_of(Uses, HasImplicit);
291}
292
293bool AliasingConfigurations::empty() const { return Configurations.empty(); }
294
295bool AliasingConfigurations::hasImplicitAliasing() const {
296 return llvm::any_of(Configurations, [](const AliasingRegisterOperands &ARO) {
297 return ARO.hasImplicitAliasing();
298 });
299}
300
301AliasingConfigurations::AliasingConfigurations(
Guillaume Chateletfcbb6f32018-10-17 11:37:28 +0000302 const Instruction &DefInstruction, const Instruction &UseInstruction) {
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000303 if (UseInstruction.AllUseRegs.anyCommon(DefInstruction.AllDefRegs)) {
304 auto CommonRegisters = UseInstruction.AllUseRegs;
305 CommonRegisters &= DefInstruction.AllDefRegs;
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000306 for (const llvm::MCPhysReg Reg : CommonRegisters.set_bits()) {
307 AliasingRegisterOperands ARO;
308 addOperandIfAlias(Reg, true, DefInstruction.Operands, ARO.Defs);
309 addOperandIfAlias(Reg, false, UseInstruction.Operands, ARO.Uses);
310 if (!ARO.Defs.empty() && !ARO.Uses.empty() &&
311 !llvm::is_contained(Configurations, ARO))
312 Configurations.push_back(std::move(ARO));
313 }
314 }
315}
316
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000317void DumpMCOperand(const llvm::MCRegisterInfo &MCRegisterInfo,
318 const llvm::MCOperand &Op, llvm::raw_ostream &OS) {
319 if (!Op.isValid())
320 OS << "Invalid";
321 else if (Op.isReg())
322 OS << MCRegisterInfo.getName(Op.getReg());
323 else if (Op.isImm())
324 OS << Op.getImm();
325 else if (Op.isFPImm())
326 OS << Op.getFPImm();
327 else if (Op.isExpr())
328 OS << "Expr";
329 else if (Op.isInst())
330 OS << "SubInst";
331}
332
333void DumpMCInst(const llvm::MCRegisterInfo &MCRegisterInfo,
334 const llvm::MCInstrInfo &MCInstrInfo,
335 const llvm::MCInst &MCInst, llvm::raw_ostream &OS) {
336 OS << MCInstrInfo.getName(MCInst.getOpcode());
337 for (unsigned I = 0, E = MCInst.getNumOperands(); I < E; ++I) {
338 if (I > 0)
339 OS << ',';
340 OS << ' ';
341 DumpMCOperand(MCRegisterInfo, MCInst.getOperand(I), OS);
342 }
343}
344
345} // namespace exegesis