blob: 2b4624b9b64223b82800fc12d6a5c7a22d7434b3 [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
Fangrui Song32401af2018-10-22 17:10:47 +000018namespace llvm {
Clement Courbet0e69e2d2018-05-17 10:52:18 +000019namespace exegesis {
20
Guillaume Chatelet09c28392018-10-09 08:59:10 +000021unsigned Variable::getIndex() const {
Guillaume Chateletfe5b0b42018-10-09 10:06:19 +000022 assert(Index >= 0 && "Index must be set");
Guillaume Chatelet09c28392018-10-09 08:59:10 +000023 return Index;
24}
Guillaume Chateletfe5b0b42018-10-09 10:06:19 +000025
Guillaume Chatelet09c28392018-10-09 08:59:10 +000026unsigned Variable::getPrimaryOperandIndex() const {
27 assert(!TiedOperands.empty());
28 return TiedOperands[0];
29}
30
Guillaume Chateletfcbb6f32018-10-17 11:37:28 +000031bool Variable::hasTiedOperands() const {
32 assert(TiedOperands.size() <= 2 &&
33 "No more than two operands can be tied together");
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}
Guillaume Chatelet09c28392018-10-09 08:59:10 +000039
Guillaume Chatelet547d2dd2018-10-09 14:51:29 +000040unsigned Operand::getIndex() const {
41 assert(Index >= 0 && "Index must be set");
42 return Index;
43}
Guillaume Chatelet09c28392018-10-09 08:59:10 +000044
45bool Operand::isExplicit() const { return Info; }
46
47bool Operand::isImplicit() const { return !Info; }
48
49bool Operand::isImplicitReg() const { return ImplicitReg; }
50
51bool Operand::isDef() const { return IsDef; }
52
53bool Operand::isUse() const { return !IsDef; }
54
55bool Operand::isReg() const { return Tracker; }
56
57bool Operand::isTied() const { return TiedToIndex >= 0; }
58
59bool Operand::isVariable() const { return VariableIndex >= 0; }
60
61bool Operand::isMemory() const {
62 return isExplicit() &&
63 getExplicitOperandInfo().OperandType == llvm::MCOI::OPERAND_MEMORY;
64}
65
66bool Operand::isImmediate() const {
67 return isExplicit() &&
68 getExplicitOperandInfo().OperandType == llvm::MCOI::OPERAND_IMMEDIATE;
69}
70
Guillaume Chatelet547d2dd2018-10-09 14:51:29 +000071unsigned Operand::getTiedToIndex() const {
72 assert(isTied() && "Operand must be tied to get the tied index");
73 assert(TiedToIndex >= 0 && "TiedToIndex must be set");
Guillaume Chatelet09c28392018-10-09 08:59:10 +000074 return TiedToIndex;
75}
76
Guillaume Chatelet547d2dd2018-10-09 14:51:29 +000077unsigned Operand::getVariableIndex() const {
78 assert(isVariable() && "Operand must be variable to get the Variable index");
79 assert(VariableIndex >= 0 && "VariableIndex must be set");
Guillaume Chatelet09c28392018-10-09 08:59:10 +000080 return VariableIndex;
81}
82
83unsigned Operand::getImplicitReg() const {
84 assert(ImplicitReg);
85 return *ImplicitReg;
86}
87
88const RegisterAliasingTracker &Operand::getRegisterAliasing() const {
89 assert(Tracker);
90 return *Tracker;
91}
92
93const llvm::MCOperandInfo &Operand::getExplicitOperandInfo() const {
94 assert(Info);
95 return *Info;
96}
97
Guillaume Chateletee9c2a172018-10-10 14:22:48 +000098Instruction::Instruction(const LLVMState &State, unsigned Opcode)
Guillaume Chatelet9b592382018-10-10 14:57:32 +000099 : Description(&State.getInstrInfo().get(Opcode)),
100 Name(State.getInstrInfo().getName(Opcode)) {
Guillaume Chateletee9c2a172018-10-10 14:22:48 +0000101 const auto &RATC = State.getRATC();
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000102 unsigned OpIndex = 0;
Guillaume Chateletee9c2a172018-10-10 14:22:48 +0000103 for (; OpIndex < Description->getNumOperands(); ++OpIndex) {
104 const auto &OpInfo = Description->opInfo_begin()[OpIndex];
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000105 Operand Operand;
106 Operand.Index = OpIndex;
Guillaume Chateletee9c2a172018-10-10 14:22:48 +0000107 Operand.IsDef = (OpIndex < Description->getNumDefs());
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000108 // TODO(gchatelet): Handle isLookupPtrRegClass.
109 if (OpInfo.RegClass >= 0)
110 Operand.Tracker = &RATC.getRegisterClass(OpInfo.RegClass);
Guillaume Chateletc9f727b2018-06-13 13:24:41 +0000111 Operand.TiedToIndex =
Guillaume Chateletee9c2a172018-10-10 14:22:48 +0000112 Description->getOperandConstraint(OpIndex, llvm::MCOI::TIED_TO);
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000113 Operand.Info = &OpInfo;
114 Operands.push_back(Operand);
115 }
Guillaume Chateletee9c2a172018-10-10 14:22:48 +0000116 for (const llvm::MCPhysReg *MCPhysReg = Description->getImplicitDefs();
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000117 MCPhysReg && *MCPhysReg; ++MCPhysReg, ++OpIndex) {
118 Operand Operand;
119 Operand.Index = OpIndex;
120 Operand.IsDef = true;
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000121 Operand.Tracker = &RATC.getRegister(*MCPhysReg);
122 Operand.ImplicitReg = MCPhysReg;
123 Operands.push_back(Operand);
124 }
Guillaume Chateletee9c2a172018-10-10 14:22:48 +0000125 for (const llvm::MCPhysReg *MCPhysReg = Description->getImplicitUses();
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000126 MCPhysReg && *MCPhysReg; ++MCPhysReg, ++OpIndex) {
127 Operand Operand;
128 Operand.Index = OpIndex;
129 Operand.IsDef = false;
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000130 Operand.Tracker = &RATC.getRegister(*MCPhysReg);
131 Operand.ImplicitReg = MCPhysReg;
132 Operands.push_back(Operand);
133 }
Guillaume Chateletc9f727b2018-06-13 13:24:41 +0000134 // Assigning Variables to non tied explicit operands.
135 Variables.reserve(Operands.size()); // Variables.size() <= Operands.size()
136 for (auto &Op : Operands)
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000137 if (Op.isExplicit() && !Op.isTied()) {
Guillaume Chateletc9f727b2018-06-13 13:24:41 +0000138 const size_t VariableIndex = Variables.size();
139 Op.VariableIndex = VariableIndex;
140 Variables.emplace_back();
141 Variables.back().Index = VariableIndex;
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000142 }
Guillaume Chateletc9f727b2018-06-13 13:24:41 +0000143 // Assigning Variables to tied operands.
144 for (auto &Op : Operands)
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000145 if (Op.isTied())
146 Op.VariableIndex = Operands[Op.getTiedToIndex()].getVariableIndex();
Guillaume Chateletc9f727b2018-06-13 13:24:41 +0000147 // Assigning Operands to Variables.
148 for (auto &Op : Operands)
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000149 if (Op.isVariable())
150 Variables[Op.getVariableIndex()].TiedOperands.push_back(Op.getIndex());
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000151 // Processing Aliasing.
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000152 ImplDefRegs = RATC.emptyRegisters();
153 ImplUseRegs = RATC.emptyRegisters();
154 AllDefRegs = RATC.emptyRegisters();
155 AllUseRegs = RATC.emptyRegisters();
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000156 for (const auto &Op : Operands) {
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000157 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;
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000167 }
168 }
169}
170
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000171const Operand &Instruction::getPrimaryOperand(const Variable &Var) const {
172 const auto PrimaryOperandIndex = Var.getPrimaryOperandIndex();
173 assert(PrimaryOperandIndex < Operands.size());
174 return Operands[PrimaryOperandIndex];
175}
176
Guillaume Chateletfb943542018-08-01 14:41:45 +0000177bool Instruction::hasMemoryOperands() const {
Fangrui Song2e83b2e2018-10-19 06:12:02 +0000178 return any_of(Operands, [](const Operand &Op) {
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000179 return Op.isReg() && Op.isExplicit() && Op.isMemory();
180 });
181}
182
183bool Instruction::hasAliasingImplicitRegisters() const {
184 return ImplDefRegs.anyCommon(ImplUseRegs);
185}
186
Guillaume Chatelet0c17cbf2018-10-10 09:12:36 +0000187bool Instruction::hasAliasingImplicitRegistersThrough(
188 const Instruction &OtherInstr) const {
189 return ImplDefRegs.anyCommon(OtherInstr.ImplUseRegs) &&
190 OtherInstr.ImplDefRegs.anyCommon(ImplUseRegs);
191}
192
193bool Instruction::hasAliasingRegistersThrough(
194 const Instruction &OtherInstr) const {
195 return AllDefRegs.anyCommon(OtherInstr.AllUseRegs) &&
196 OtherInstr.AllDefRegs.anyCommon(AllUseRegs);
197}
198
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000199bool Instruction::hasTiedRegisters() const {
200 return llvm::any_of(
Guillaume Chateletcf6d5fa2018-10-09 09:33:29 +0000201 Variables, [](const Variable &Var) { return Var.hasTiedOperands(); });
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000202}
203
204bool Instruction::hasAliasingRegisters() const {
205 return AllDefRegs.anyCommon(AllUseRegs);
Guillaume Chateletfb943542018-08-01 14:41:45 +0000206}
207
Guillaume Chateletfcbb6f32018-10-17 11:37:28 +0000208bool Instruction::hasOneUseOrOneDef() const {
209 return AllDefRegs.count() || AllUseRegs.count();
210}
211
Guillaume Chatelet22cccff2018-10-09 14:51:33 +0000212void Instruction::dump(const llvm::MCRegisterInfo &RegInfo,
Guillaume Chatelet547d2dd2018-10-09 14:51:29 +0000213 llvm::raw_ostream &Stream) const {
Guillaume Chatelet9b592382018-10-10 14:57:32 +0000214 Stream << "- " << Name << "\n";
Guillaume Chatelet547d2dd2018-10-09 14:51:29 +0000215 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();
Guillaume Chatelet9b592382018-10-10 14:57:32 +0000244 Stream << " [";
245 bool IsFirst = true;
246 for (auto OperandIndex : Var.TiedOperands) {
247 if (!IsFirst)
248 Stream << ",";
Guillaume Chatelet0c17cbf2018-10-10 09:12:36 +0000249 Stream << "Op" << OperandIndex;
Guillaume Chatelet9b592382018-10-10 14:57:32 +0000250 IsFirst = false;
251 }
252 Stream << "]";
Guillaume Chatelet547d2dd2018-10-09 14:51:29 +0000253 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
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000265bool RegisterOperandAssignment::
266operator==(const RegisterOperandAssignment &Other) const {
267 return std::tie(Op, Reg) == std::tie(Other.Op, Other.Reg);
268}
269
270bool AliasingRegisterOperands::
271operator==(const AliasingRegisterOperands &Other) const {
272 return std::tie(Defs, Uses) == std::tie(Other.Defs, Other.Uses);
273}
274
275static void addOperandIfAlias(
276 const llvm::MCPhysReg Reg, bool SelectDef, llvm::ArrayRef<Operand> Operands,
277 llvm::SmallVectorImpl<RegisterOperandAssignment> &OperandValues) {
278 for (const auto &Op : Operands) {
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000279 if (Op.isReg() && Op.isDef() == SelectDef) {
280 const int SourceReg = Op.getRegisterAliasing().getOrigin(Reg);
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000281 if (SourceReg >= 0)
282 OperandValues.emplace_back(&Op, SourceReg);
283 }
284 }
285}
286
287bool AliasingRegisterOperands::hasImplicitAliasing() const {
288 const auto HasImplicit = [](const RegisterOperandAssignment &ROV) {
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000289 return ROV.Op->isImplicit();
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000290 };
291 return llvm::any_of(Defs, HasImplicit) && llvm::any_of(Uses, HasImplicit);
292}
293
294bool AliasingConfigurations::empty() const { return Configurations.empty(); }
295
296bool AliasingConfigurations::hasImplicitAliasing() const {
297 return llvm::any_of(Configurations, [](const AliasingRegisterOperands &ARO) {
298 return ARO.hasImplicitAliasing();
299 });
300}
301
302AliasingConfigurations::AliasingConfigurations(
Guillaume Chateletfcbb6f32018-10-17 11:37:28 +0000303 const Instruction &DefInstruction, const Instruction &UseInstruction) {
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000304 if (UseInstruction.AllUseRegs.anyCommon(DefInstruction.AllDefRegs)) {
305 auto CommonRegisters = UseInstruction.AllUseRegs;
306 CommonRegisters &= DefInstruction.AllDefRegs;
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000307 for (const llvm::MCPhysReg Reg : CommonRegisters.set_bits()) {
308 AliasingRegisterOperands ARO;
309 addOperandIfAlias(Reg, true, DefInstruction.Operands, ARO.Defs);
310 addOperandIfAlias(Reg, false, UseInstruction.Operands, ARO.Uses);
311 if (!ARO.Defs.empty() && !ARO.Uses.empty() &&
312 !llvm::is_contained(Configurations, ARO))
313 Configurations.push_back(std::move(ARO));
314 }
315 }
316}
317
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000318void DumpMCOperand(const llvm::MCRegisterInfo &MCRegisterInfo,
319 const llvm::MCOperand &Op, llvm::raw_ostream &OS) {
320 if (!Op.isValid())
321 OS << "Invalid";
322 else if (Op.isReg())
323 OS << MCRegisterInfo.getName(Op.getReg());
324 else if (Op.isImm())
325 OS << Op.getImm();
326 else if (Op.isFPImm())
327 OS << Op.getFPImm();
328 else if (Op.isExpr())
329 OS << "Expr";
330 else if (Op.isInst())
331 OS << "SubInst";
332}
333
334void DumpMCInst(const llvm::MCRegisterInfo &MCRegisterInfo,
335 const llvm::MCInstrInfo &MCInstrInfo,
336 const llvm::MCInst &MCInst, llvm::raw_ostream &OS) {
337 OS << MCInstrInfo.getName(MCInst.getOpcode());
338 for (unsigned I = 0, E = MCInst.getNumOperands(); I < E; ++I) {
339 if (I > 0)
340 OS << ',';
341 OS << ' ';
342 DumpMCOperand(MCRegisterInfo, MCInst.getOperand(I), OS);
343 }
344}
345
346} // namespace exegesis
Fangrui Song32401af2018-10-22 17:10:47 +0000347} // namespace llvm