blob: e0521af4d19e11bc8899c9ed0720447633f819d9 [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 Chateletda11b852018-10-24 11:55:06 +000098Instruction::Instruction(const llvm::MCInstrInfo &InstrInfo,
99 const RegisterAliasingTrackerCache &RATC,
100 unsigned Opcode)
101 : Description(&InstrInfo.get(Opcode)), Name(InstrInfo.getName(Opcode)) {
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
Guillaume Chateletda11b852018-10-24 11:55:06 +0000265InstructionsCache::InstructionsCache(const llvm::MCInstrInfo &InstrInfo,
266 const RegisterAliasingTrackerCache &RATC)
267 : InstrInfo(InstrInfo), RATC(RATC) {}
268
269const Instruction &InstructionsCache::getInstr(unsigned Opcode) const {
270 auto &Found = Instructions[Opcode];
271 if (!Found)
272 Found.reset(new Instruction(InstrInfo, RATC, Opcode));
273 return *Found;
274}
275
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000276bool RegisterOperandAssignment::
277operator==(const RegisterOperandAssignment &Other) const {
278 return std::tie(Op, Reg) == std::tie(Other.Op, Other.Reg);
279}
280
281bool AliasingRegisterOperands::
282operator==(const AliasingRegisterOperands &Other) const {
283 return std::tie(Defs, Uses) == std::tie(Other.Defs, Other.Uses);
284}
285
286static void addOperandIfAlias(
287 const llvm::MCPhysReg Reg, bool SelectDef, llvm::ArrayRef<Operand> Operands,
288 llvm::SmallVectorImpl<RegisterOperandAssignment> &OperandValues) {
289 for (const auto &Op : Operands) {
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000290 if (Op.isReg() && Op.isDef() == SelectDef) {
291 const int SourceReg = Op.getRegisterAliasing().getOrigin(Reg);
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000292 if (SourceReg >= 0)
293 OperandValues.emplace_back(&Op, SourceReg);
294 }
295 }
296}
297
298bool AliasingRegisterOperands::hasImplicitAliasing() const {
299 const auto HasImplicit = [](const RegisterOperandAssignment &ROV) {
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000300 return ROV.Op->isImplicit();
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000301 };
302 return llvm::any_of(Defs, HasImplicit) && llvm::any_of(Uses, HasImplicit);
303}
304
305bool AliasingConfigurations::empty() const { return Configurations.empty(); }
306
307bool AliasingConfigurations::hasImplicitAliasing() const {
308 return llvm::any_of(Configurations, [](const AliasingRegisterOperands &ARO) {
309 return ARO.hasImplicitAliasing();
310 });
311}
312
313AliasingConfigurations::AliasingConfigurations(
Guillaume Chateletfcbb6f32018-10-17 11:37:28 +0000314 const Instruction &DefInstruction, const Instruction &UseInstruction) {
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000315 if (UseInstruction.AllUseRegs.anyCommon(DefInstruction.AllDefRegs)) {
316 auto CommonRegisters = UseInstruction.AllUseRegs;
317 CommonRegisters &= DefInstruction.AllDefRegs;
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000318 for (const llvm::MCPhysReg Reg : CommonRegisters.set_bits()) {
319 AliasingRegisterOperands ARO;
320 addOperandIfAlias(Reg, true, DefInstruction.Operands, ARO.Defs);
321 addOperandIfAlias(Reg, false, UseInstruction.Operands, ARO.Uses);
322 if (!ARO.Defs.empty() && !ARO.Uses.empty() &&
323 !llvm::is_contained(Configurations, ARO))
324 Configurations.push_back(std::move(ARO));
325 }
326 }
327}
328
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000329void DumpMCOperand(const llvm::MCRegisterInfo &MCRegisterInfo,
330 const llvm::MCOperand &Op, llvm::raw_ostream &OS) {
331 if (!Op.isValid())
332 OS << "Invalid";
333 else if (Op.isReg())
334 OS << MCRegisterInfo.getName(Op.getReg());
335 else if (Op.isImm())
336 OS << Op.getImm();
337 else if (Op.isFPImm())
338 OS << Op.getFPImm();
339 else if (Op.isExpr())
340 OS << "Expr";
341 else if (Op.isInst())
342 OS << "SubInst";
343}
344
345void DumpMCInst(const llvm::MCRegisterInfo &MCRegisterInfo,
346 const llvm::MCInstrInfo &MCInstrInfo,
347 const llvm::MCInst &MCInst, llvm::raw_ostream &OS) {
348 OS << MCInstrInfo.getName(MCInst.getOpcode());
349 for (unsigned I = 0, E = MCInst.getNumOperands(); I < E; ++I) {
350 if (I > 0)
351 OS << ',';
352 OS << ' ';
353 DumpMCOperand(MCRegisterInfo, MCInst.getOperand(I), OS);
354 }
355}
356
357} // namespace exegesis
Fangrui Song32401af2018-10-22 17:10:47 +0000358} // namespace llvm