blob: 487f6641d5079766b8c0775f65143986497911d0 [file] [log] [blame]
Clement Courbet0e69e2d2018-05-17 10:52:18 +00001//===-- MCInstrDescView.cpp -------------------------------------*- C++ -*-===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Clement Courbet0e69e2d2018-05-17 10:52:18 +00006//
7//===----------------------------------------------------------------------===//
8
9#include "MCInstrDescView.h"
10
11#include <iterator>
12#include <map>
13#include <tuple>
14
15#include "llvm/ADT/STLExtras.h"
16
Fangrui Song32401af2018-10-22 17:10:47 +000017namespace llvm {
Clement Courbet0e69e2d2018-05-17 10:52:18 +000018namespace exegesis {
19
Guillaume Chatelet32d384c2019-12-18 12:08:38 +010020unsigned Variable::getIndex() const { return *Index; }
Guillaume Chateletfe5b0b42018-10-09 10:06:19 +000021
Guillaume Chatelet09c28392018-10-09 08:59:10 +000022unsigned Variable::getPrimaryOperandIndex() const {
23 assert(!TiedOperands.empty());
24 return TiedOperands[0];
25}
26
Guillaume Chateletfcbb6f32018-10-17 11:37:28 +000027bool Variable::hasTiedOperands() const {
28 assert(TiedOperands.size() <= 2 &&
29 "No more than two operands can be tied together");
30 // By definition only Use and Def operands can be tied together.
31 // TiedOperands[0] is the Def operand (LLVM stores defs first).
32 // TiedOperands[1] is the Use operand.
33 return TiedOperands.size() > 1;
34}
Guillaume Chatelet09c28392018-10-09 08:59:10 +000035
Guillaume Chatelet32d384c2019-12-18 12:08:38 +010036unsigned Operand::getIndex() const { return *Index; }
Guillaume Chatelet09c28392018-10-09 08:59:10 +000037
38bool Operand::isExplicit() const { return Info; }
39
40bool Operand::isImplicit() const { return !Info; }
41
42bool Operand::isImplicitReg() const { return ImplicitReg; }
43
44bool Operand::isDef() const { return IsDef; }
45
46bool Operand::isUse() const { return !IsDef; }
47
48bool Operand::isReg() const { return Tracker; }
49
Guillaume Chatelet32d384c2019-12-18 12:08:38 +010050bool Operand::isTied() const { return TiedToIndex.hasValue(); }
Guillaume Chatelet09c28392018-10-09 08:59:10 +000051
Guillaume Chatelet32d384c2019-12-18 12:08:38 +010052bool Operand::isVariable() const { return VariableIndex.hasValue(); }
Guillaume Chatelet09c28392018-10-09 08:59:10 +000053
54bool Operand::isMemory() const {
55 return isExplicit() &&
Clement Courbet50cdd562019-10-09 11:58:42 +000056 getExplicitOperandInfo().OperandType == MCOI::OPERAND_MEMORY;
Guillaume Chatelet09c28392018-10-09 08:59:10 +000057}
58
59bool Operand::isImmediate() const {
60 return isExplicit() &&
Clement Courbet50cdd562019-10-09 11:58:42 +000061 getExplicitOperandInfo().OperandType == MCOI::OPERAND_IMMEDIATE;
Guillaume Chatelet09c28392018-10-09 08:59:10 +000062}
63
Guillaume Chatelet32d384c2019-12-18 12:08:38 +010064unsigned Operand::getTiedToIndex() const { return *TiedToIndex; }
Guillaume Chatelet09c28392018-10-09 08:59:10 +000065
Guillaume Chatelet32d384c2019-12-18 12:08:38 +010066unsigned Operand::getVariableIndex() const { return *VariableIndex; }
Guillaume Chatelet09c28392018-10-09 08:59:10 +000067
68unsigned Operand::getImplicitReg() const {
69 assert(ImplicitReg);
70 return *ImplicitReg;
71}
72
73const RegisterAliasingTracker &Operand::getRegisterAliasing() const {
74 assert(Tracker);
75 return *Tracker;
76}
77
Clement Courbet50cdd562019-10-09 11:58:42 +000078const MCOperandInfo &Operand::getExplicitOperandInfo() const {
Guillaume Chatelet09c28392018-10-09 08:59:10 +000079 assert(Info);
80 return *Info;
81}
82
Guillaume Chatelet32d384c2019-12-18 12:08:38 +010083const BitVector *BitVectorCache::getUnique(BitVector &&BV) const {
84 for (const auto &Entry : Cache)
85 if (*Entry == BV)
86 return Entry.get();
87 Cache.push_back(std::make_unique<BitVector>());
88 auto &Entry = Cache.back();
89 Entry->swap(BV);
90 return Entry.get();
91}
92
93Instruction::Instruction(const MCInstrDesc *Description, StringRef Name,
94 SmallVector<Operand, 8> Operands,
95 SmallVector<Variable, 4> Variables,
96 const BitVector *ImplDefRegs,
97 const BitVector *ImplUseRegs,
98 const BitVector *AllDefRegs,
99 const BitVector *AllUseRegs)
100 : Description(*Description), Name(Name), Operands(std::move(Operands)),
101 Variables(std::move(Variables)), ImplDefRegs(*ImplDefRegs),
102 ImplUseRegs(*ImplUseRegs), AllDefRegs(*AllDefRegs),
103 AllUseRegs(*AllUseRegs) {}
104
105std::unique_ptr<Instruction>
106Instruction::create(const MCInstrInfo &InstrInfo,
107 const RegisterAliasingTrackerCache &RATC,
108 const BitVectorCache &BVC, unsigned Opcode) {
109 const llvm::MCInstrDesc *const Description = &InstrInfo.get(Opcode);
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000110 unsigned OpIndex = 0;
Guillaume Chatelet32d384c2019-12-18 12:08:38 +0100111 SmallVector<Operand, 8> Operands;
112 SmallVector<Variable, 4> Variables;
Guillaume Chateletee9c2a172018-10-10 14:22:48 +0000113 for (; OpIndex < Description->getNumOperands(); ++OpIndex) {
114 const auto &OpInfo = Description->opInfo_begin()[OpIndex];
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000115 Operand Operand;
116 Operand.Index = OpIndex;
Guillaume Chateletee9c2a172018-10-10 14:22:48 +0000117 Operand.IsDef = (OpIndex < Description->getNumDefs());
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000118 // TODO(gchatelet): Handle isLookupPtrRegClass.
119 if (OpInfo.RegClass >= 0)
120 Operand.Tracker = &RATC.getRegisterClass(OpInfo.RegClass);
Guillaume Chatelet32d384c2019-12-18 12:08:38 +0100121 int TiedToIndex = Description->getOperandConstraint(OpIndex, MCOI::TIED_TO);
122 assert(TiedToIndex == -1 ||
123 TiedToIndex < std::numeric_limits<uint8_t>::max());
124 if (TiedToIndex >= 0)
125 Operand.TiedToIndex = TiedToIndex;
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000126 Operand.Info = &OpInfo;
127 Operands.push_back(Operand);
128 }
Clement Courbet50cdd562019-10-09 11:58:42 +0000129 for (const MCPhysReg *MCPhysReg = Description->getImplicitDefs();
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000130 MCPhysReg && *MCPhysReg; ++MCPhysReg, ++OpIndex) {
131 Operand Operand;
132 Operand.Index = OpIndex;
133 Operand.IsDef = true;
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000134 Operand.Tracker = &RATC.getRegister(*MCPhysReg);
135 Operand.ImplicitReg = MCPhysReg;
136 Operands.push_back(Operand);
137 }
Clement Courbet50cdd562019-10-09 11:58:42 +0000138 for (const MCPhysReg *MCPhysReg = Description->getImplicitUses();
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000139 MCPhysReg && *MCPhysReg; ++MCPhysReg, ++OpIndex) {
140 Operand Operand;
141 Operand.Index = OpIndex;
142 Operand.IsDef = false;
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000143 Operand.Tracker = &RATC.getRegister(*MCPhysReg);
144 Operand.ImplicitReg = MCPhysReg;
145 Operands.push_back(Operand);
146 }
Guillaume Chateletc9f727b2018-06-13 13:24:41 +0000147 Variables.reserve(Operands.size()); // Variables.size() <= Operands.size()
Guillaume Chatelet32d384c2019-12-18 12:08:38 +0100148 // Assigning Variables to non tied explicit operands.
Guillaume Chateletc9f727b2018-06-13 13:24:41 +0000149 for (auto &Op : Operands)
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000150 if (Op.isExplicit() && !Op.isTied()) {
Guillaume Chateletc9f727b2018-06-13 13:24:41 +0000151 const size_t VariableIndex = Variables.size();
Guillaume Chatelet32d384c2019-12-18 12:08:38 +0100152 assert(VariableIndex < std::numeric_limits<uint8_t>::max());
Guillaume Chateletc9f727b2018-06-13 13:24:41 +0000153 Op.VariableIndex = VariableIndex;
154 Variables.emplace_back();
155 Variables.back().Index = VariableIndex;
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000156 }
Guillaume Chateletc9f727b2018-06-13 13:24:41 +0000157 // Assigning Variables to tied operands.
158 for (auto &Op : Operands)
Guillaume Chatelet32d384c2019-12-18 12:08:38 +0100159 if (Op.isExplicit() && Op.isTied())
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000160 Op.VariableIndex = Operands[Op.getTiedToIndex()].getVariableIndex();
Guillaume Chateletc9f727b2018-06-13 13:24:41 +0000161 // Assigning Operands to Variables.
162 for (auto &Op : Operands)
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000163 if (Op.isVariable())
164 Variables[Op.getVariableIndex()].TiedOperands.push_back(Op.getIndex());
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000165 // Processing Aliasing.
Guillaume Chatelet32d384c2019-12-18 12:08:38 +0100166 BitVector ImplDefRegs = RATC.emptyRegisters();
167 BitVector ImplUseRegs = RATC.emptyRegisters();
168 BitVector AllDefRegs = RATC.emptyRegisters();
169 BitVector AllUseRegs = RATC.emptyRegisters();
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000170 for (const auto &Op : Operands) {
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000171 if (Op.isReg()) {
172 const auto &AliasingBits = Op.getRegisterAliasing().aliasedBits();
173 if (Op.isDef())
174 AllDefRegs |= AliasingBits;
175 if (Op.isUse())
176 AllUseRegs |= AliasingBits;
177 if (Op.isDef() && Op.isImplicit())
178 ImplDefRegs |= AliasingBits;
179 if (Op.isUse() && Op.isImplicit())
180 ImplUseRegs |= AliasingBits;
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000181 }
182 }
Guillaume Chatelet32d384c2019-12-18 12:08:38 +0100183 // Can't use make_unique because constructor is private.
184 return std::unique_ptr<Instruction>(new Instruction(
185 Description, InstrInfo.getName(Opcode), std::move(Operands),
186 std::move(Variables), BVC.getUnique(std::move(ImplDefRegs)),
187 BVC.getUnique(std::move(ImplUseRegs)),
188 BVC.getUnique(std::move(AllDefRegs)),
189 BVC.getUnique(std::move(AllUseRegs))));
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000190}
191
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000192const Operand &Instruction::getPrimaryOperand(const Variable &Var) const {
193 const auto PrimaryOperandIndex = Var.getPrimaryOperandIndex();
194 assert(PrimaryOperandIndex < Operands.size());
195 return Operands[PrimaryOperandIndex];
196}
197
Guillaume Chateletfb943542018-08-01 14:41:45 +0000198bool Instruction::hasMemoryOperands() const {
Fangrui Song2e83b2e2018-10-19 06:12:02 +0000199 return any_of(Operands, [](const Operand &Op) {
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000200 return Op.isReg() && Op.isExplicit() && Op.isMemory();
201 });
202}
203
204bool Instruction::hasAliasingImplicitRegisters() const {
205 return ImplDefRegs.anyCommon(ImplUseRegs);
206}
207
Clement Courbet8ef97e12019-09-27 08:04:10 +0000208// Returns true if there are registers that are both in `A` and `B` but not in
209// `Forbidden`.
210static bool anyCommonExcludingForbidden(const BitVector &A, const BitVector &B,
211 const BitVector &Forbidden) {
212 assert(A.size() == B.size() && B.size() == Forbidden.size());
213 const auto Size = A.size();
214 for (int AIndex = A.find_first(); AIndex != -1;) {
215 const int BIndex = B.find_first_in(AIndex, Size);
216 if (BIndex == -1)
217 return false;
218 if (AIndex == BIndex && !Forbidden.test(AIndex))
219 return true;
220 AIndex = A.find_first_in(BIndex + 1, Size);
221 }
222 return false;
223}
224
Guillaume Chatelet0c17cbf2018-10-10 09:12:36 +0000225bool Instruction::hasAliasingRegistersThrough(
Clement Courbet8ef97e12019-09-27 08:04:10 +0000226 const Instruction &OtherInstr, const BitVector &ForbiddenRegisters) const {
227 return anyCommonExcludingForbidden(AllDefRegs, OtherInstr.AllUseRegs,
228 ForbiddenRegisters) &&
229 anyCommonExcludingForbidden(OtherInstr.AllDefRegs, AllUseRegs,
230 ForbiddenRegisters);
Guillaume Chatelet0c17cbf2018-10-10 09:12:36 +0000231}
232
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000233bool Instruction::hasTiedRegisters() const {
Clement Courbet50cdd562019-10-09 11:58:42 +0000234 return any_of(Variables,
235 [](const Variable &Var) { return Var.hasTiedOperands(); });
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000236}
237
Clement Courbet8ef97e12019-09-27 08:04:10 +0000238bool Instruction::hasAliasingRegisters(
239 const BitVector &ForbiddenRegisters) const {
240 return anyCommonExcludingForbidden(AllDefRegs, AllUseRegs,
241 ForbiddenRegisters);
Guillaume Chateletfb943542018-08-01 14:41:45 +0000242}
243
Guillaume Chateletfcbb6f32018-10-17 11:37:28 +0000244bool Instruction::hasOneUseOrOneDef() const {
245 return AllDefRegs.count() || AllUseRegs.count();
246}
247
Clement Courbet50cdd562019-10-09 11:58:42 +0000248void Instruction::dump(const MCRegisterInfo &RegInfo,
Clement Courbet8ef97e12019-09-27 08:04:10 +0000249 const RegisterAliasingTrackerCache &RATC,
Clement Courbet50cdd562019-10-09 11:58:42 +0000250 raw_ostream &Stream) const {
Guillaume Chatelet9b592382018-10-10 14:57:32 +0000251 Stream << "- " << Name << "\n";
Guillaume Chatelet547d2dd2018-10-09 14:51:29 +0000252 for (const auto &Op : Operands) {
253 Stream << "- Op" << Op.getIndex();
254 if (Op.isExplicit())
255 Stream << " Explicit";
256 if (Op.isImplicit())
257 Stream << " Implicit";
258 if (Op.isUse())
259 Stream << " Use";
260 if (Op.isDef())
261 Stream << " Def";
262 if (Op.isImmediate())
263 Stream << " Immediate";
264 if (Op.isMemory())
265 Stream << " Memory";
266 if (Op.isReg()) {
267 if (Op.isImplicitReg())
268 Stream << " Reg(" << RegInfo.getName(Op.getImplicitReg()) << ")";
269 else
270 Stream << " RegClass("
271 << RegInfo.getRegClassName(
272 &RegInfo.getRegClass(Op.Info->RegClass))
273 << ")";
274 }
275 if (Op.isTied())
276 Stream << " TiedToOp" << Op.getTiedToIndex();
277 Stream << "\n";
278 }
279 for (const auto &Var : Variables) {
280 Stream << "- Var" << Var.getIndex();
Guillaume Chatelet9b592382018-10-10 14:57:32 +0000281 Stream << " [";
282 bool IsFirst = true;
283 for (auto OperandIndex : Var.TiedOperands) {
284 if (!IsFirst)
285 Stream << ",";
Guillaume Chatelet0c17cbf2018-10-10 09:12:36 +0000286 Stream << "Op" << OperandIndex;
Guillaume Chatelet9b592382018-10-10 14:57:32 +0000287 IsFirst = false;
288 }
289 Stream << "]";
Guillaume Chatelet547d2dd2018-10-09 14:51:29 +0000290 Stream << "\n";
291 }
292 if (hasMemoryOperands())
293 Stream << "- hasMemoryOperands\n";
294 if (hasAliasingImplicitRegisters())
295 Stream << "- hasAliasingImplicitRegisters (execution is always serial)\n";
296 if (hasTiedRegisters())
297 Stream << "- hasTiedRegisters (execution is always serial)\n";
Clement Courbet8ef97e12019-09-27 08:04:10 +0000298 if (hasAliasingRegisters(RATC.emptyRegisters()))
Guillaume Chatelet547d2dd2018-10-09 14:51:29 +0000299 Stream << "- hasAliasingRegisters\n";
300}
301
Clement Courbet50cdd562019-10-09 11:58:42 +0000302InstructionsCache::InstructionsCache(const MCInstrInfo &InstrInfo,
Guillaume Chateletda11b852018-10-24 11:55:06 +0000303 const RegisterAliasingTrackerCache &RATC)
304 : InstrInfo(InstrInfo), RATC(RATC) {}
305
306const Instruction &InstructionsCache::getInstr(unsigned Opcode) const {
307 auto &Found = Instructions[Opcode];
308 if (!Found)
Guillaume Chatelet32d384c2019-12-18 12:08:38 +0100309 Found = Instruction::create(InstrInfo, RATC, BVC, Opcode);
Guillaume Chateletda11b852018-10-24 11:55:06 +0000310 return *Found;
311}
312
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000313bool RegisterOperandAssignment::
314operator==(const RegisterOperandAssignment &Other) const {
315 return std::tie(Op, Reg) == std::tie(Other.Op, Other.Reg);
316}
317
318bool AliasingRegisterOperands::
319operator==(const AliasingRegisterOperands &Other) const {
320 return std::tie(Defs, Uses) == std::tie(Other.Defs, Other.Uses);
321}
322
Clement Courbet50cdd562019-10-09 11:58:42 +0000323static void
324addOperandIfAlias(const MCPhysReg Reg, bool SelectDef,
325 ArrayRef<Operand> Operands,
326 SmallVectorImpl<RegisterOperandAssignment> &OperandValues) {
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000327 for (const auto &Op : Operands) {
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000328 if (Op.isReg() && Op.isDef() == SelectDef) {
329 const int SourceReg = Op.getRegisterAliasing().getOrigin(Reg);
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000330 if (SourceReg >= 0)
331 OperandValues.emplace_back(&Op, SourceReg);
332 }
333 }
334}
335
336bool AliasingRegisterOperands::hasImplicitAliasing() const {
337 const auto HasImplicit = [](const RegisterOperandAssignment &ROV) {
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000338 return ROV.Op->isImplicit();
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000339 };
Clement Courbet50cdd562019-10-09 11:58:42 +0000340 return any_of(Defs, HasImplicit) && any_of(Uses, HasImplicit);
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000341}
342
343bool AliasingConfigurations::empty() const { return Configurations.empty(); }
344
345bool AliasingConfigurations::hasImplicitAliasing() const {
Clement Courbet50cdd562019-10-09 11:58:42 +0000346 return any_of(Configurations, [](const AliasingRegisterOperands &ARO) {
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000347 return ARO.hasImplicitAliasing();
348 });
349}
350
351AliasingConfigurations::AliasingConfigurations(
Guillaume Chateletfcbb6f32018-10-17 11:37:28 +0000352 const Instruction &DefInstruction, const Instruction &UseInstruction) {
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000353 if (UseInstruction.AllUseRegs.anyCommon(DefInstruction.AllDefRegs)) {
354 auto CommonRegisters = UseInstruction.AllUseRegs;
355 CommonRegisters &= DefInstruction.AllDefRegs;
Clement Courbet50cdd562019-10-09 11:58:42 +0000356 for (const MCPhysReg Reg : CommonRegisters.set_bits()) {
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000357 AliasingRegisterOperands ARO;
358 addOperandIfAlias(Reg, true, DefInstruction.Operands, ARO.Defs);
359 addOperandIfAlias(Reg, false, UseInstruction.Operands, ARO.Uses);
360 if (!ARO.Defs.empty() && !ARO.Uses.empty() &&
Clement Courbet50cdd562019-10-09 11:58:42 +0000361 !is_contained(Configurations, ARO))
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000362 Configurations.push_back(std::move(ARO));
363 }
364 }
365}
366
Clement Courbet50cdd562019-10-09 11:58:42 +0000367void DumpMCOperand(const MCRegisterInfo &MCRegisterInfo, const MCOperand &Op,
368 raw_ostream &OS) {
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000369 if (!Op.isValid())
370 OS << "Invalid";
371 else if (Op.isReg())
372 OS << MCRegisterInfo.getName(Op.getReg());
373 else if (Op.isImm())
374 OS << Op.getImm();
375 else if (Op.isFPImm())
376 OS << Op.getFPImm();
377 else if (Op.isExpr())
378 OS << "Expr";
379 else if (Op.isInst())
380 OS << "SubInst";
381}
382
Clement Courbet50cdd562019-10-09 11:58:42 +0000383void DumpMCInst(const MCRegisterInfo &MCRegisterInfo,
384 const MCInstrInfo &MCInstrInfo, const MCInst &MCInst,
385 raw_ostream &OS) {
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000386 OS << MCInstrInfo.getName(MCInst.getOpcode());
387 for (unsigned I = 0, E = MCInst.getNumOperands(); I < E; ++I) {
388 if (I > 0)
389 OS << ',';
390 OS << ' ';
391 DumpMCOperand(MCRegisterInfo, MCInst.getOperand(I), OS);
392 }
393}
394
395} // namespace exegesis
Fangrui Song32401af2018-10-22 17:10:47 +0000396} // namespace llvm