blob: 9b3c50f8d9ec8e0b62f41262eb70d98989560925 [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 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() &&
Clement Courbet50cdd562019-10-09 11:58:42 +000062 getExplicitOperandInfo().OperandType == MCOI::OPERAND_MEMORY;
Guillaume Chatelet09c28392018-10-09 08:59:10 +000063}
64
65bool Operand::isImmediate() const {
66 return isExplicit() &&
Clement Courbet50cdd562019-10-09 11:58:42 +000067 getExplicitOperandInfo().OperandType == MCOI::OPERAND_IMMEDIATE;
Guillaume Chatelet09c28392018-10-09 08:59:10 +000068}
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
Clement Courbet50cdd562019-10-09 11:58:42 +000092const MCOperandInfo &Operand::getExplicitOperandInfo() const {
Guillaume Chatelet09c28392018-10-09 08:59:10 +000093 assert(Info);
94 return *Info;
95}
96
Clement Courbet50cdd562019-10-09 11:58:42 +000097Instruction::Instruction(const MCInstrInfo &InstrInfo,
Guillaume Chateletda11b852018-10-24 11:55:06 +000098 const RegisterAliasingTrackerCache &RATC,
99 unsigned Opcode)
100 : Description(&InstrInfo.get(Opcode)), Name(InstrInfo.getName(Opcode)) {
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 =
Clement Courbet50cdd562019-10-09 11:58:42 +0000111 Description->getOperandConstraint(OpIndex, MCOI::TIED_TO);
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000112 Operand.Info = &OpInfo;
113 Operands.push_back(Operand);
114 }
Clement Courbet50cdd562019-10-09 11:58:42 +0000115 for (const 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 }
Clement Courbet50cdd562019-10-09 11:58:42 +0000124 for (const 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 {
Fangrui Song2e83b2e2018-10-19 06:12:02 +0000177 return any_of(Operands, [](const Operand &Op) {
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000178 return Op.isReg() && Op.isExplicit() && Op.isMemory();
179 });
180}
181
182bool Instruction::hasAliasingImplicitRegisters() const {
183 return ImplDefRegs.anyCommon(ImplUseRegs);
184}
185
Clement Courbet8ef97e12019-09-27 08:04:10 +0000186// Returns true if there are registers that are both in `A` and `B` but not in
187// `Forbidden`.
188static bool anyCommonExcludingForbidden(const BitVector &A, const BitVector &B,
189 const BitVector &Forbidden) {
190 assert(A.size() == B.size() && B.size() == Forbidden.size());
191 const auto Size = A.size();
192 for (int AIndex = A.find_first(); AIndex != -1;) {
193 const int BIndex = B.find_first_in(AIndex, Size);
194 if (BIndex == -1)
195 return false;
196 if (AIndex == BIndex && !Forbidden.test(AIndex))
197 return true;
198 AIndex = A.find_first_in(BIndex + 1, Size);
199 }
200 return false;
201}
202
Guillaume Chatelet0c17cbf2018-10-10 09:12:36 +0000203bool Instruction::hasAliasingRegistersThrough(
Clement Courbet8ef97e12019-09-27 08:04:10 +0000204 const Instruction &OtherInstr, const BitVector &ForbiddenRegisters) const {
205 return anyCommonExcludingForbidden(AllDefRegs, OtherInstr.AllUseRegs,
206 ForbiddenRegisters) &&
207 anyCommonExcludingForbidden(OtherInstr.AllDefRegs, AllUseRegs,
208 ForbiddenRegisters);
Guillaume Chatelet0c17cbf2018-10-10 09:12:36 +0000209}
210
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000211bool Instruction::hasTiedRegisters() const {
Clement Courbet50cdd562019-10-09 11:58:42 +0000212 return any_of(Variables,
213 [](const Variable &Var) { return Var.hasTiedOperands(); });
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000214}
215
Clement Courbet8ef97e12019-09-27 08:04:10 +0000216bool Instruction::hasAliasingRegisters(
217 const BitVector &ForbiddenRegisters) const {
218 return anyCommonExcludingForbidden(AllDefRegs, AllUseRegs,
219 ForbiddenRegisters);
Guillaume Chateletfb943542018-08-01 14:41:45 +0000220}
221
Guillaume Chateletfcbb6f32018-10-17 11:37:28 +0000222bool Instruction::hasOneUseOrOneDef() const {
223 return AllDefRegs.count() || AllUseRegs.count();
224}
225
Clement Courbet50cdd562019-10-09 11:58:42 +0000226void Instruction::dump(const MCRegisterInfo &RegInfo,
Clement Courbet8ef97e12019-09-27 08:04:10 +0000227 const RegisterAliasingTrackerCache &RATC,
Clement Courbet50cdd562019-10-09 11:58:42 +0000228 raw_ostream &Stream) const {
Guillaume Chatelet9b592382018-10-10 14:57:32 +0000229 Stream << "- " << Name << "\n";
Guillaume Chatelet547d2dd2018-10-09 14:51:29 +0000230 for (const auto &Op : Operands) {
231 Stream << "- Op" << Op.getIndex();
232 if (Op.isExplicit())
233 Stream << " Explicit";
234 if (Op.isImplicit())
235 Stream << " Implicit";
236 if (Op.isUse())
237 Stream << " Use";
238 if (Op.isDef())
239 Stream << " Def";
240 if (Op.isImmediate())
241 Stream << " Immediate";
242 if (Op.isMemory())
243 Stream << " Memory";
244 if (Op.isReg()) {
245 if (Op.isImplicitReg())
246 Stream << " Reg(" << RegInfo.getName(Op.getImplicitReg()) << ")";
247 else
248 Stream << " RegClass("
249 << RegInfo.getRegClassName(
250 &RegInfo.getRegClass(Op.Info->RegClass))
251 << ")";
252 }
253 if (Op.isTied())
254 Stream << " TiedToOp" << Op.getTiedToIndex();
255 Stream << "\n";
256 }
257 for (const auto &Var : Variables) {
258 Stream << "- Var" << Var.getIndex();
Guillaume Chatelet9b592382018-10-10 14:57:32 +0000259 Stream << " [";
260 bool IsFirst = true;
261 for (auto OperandIndex : Var.TiedOperands) {
262 if (!IsFirst)
263 Stream << ",";
Guillaume Chatelet0c17cbf2018-10-10 09:12:36 +0000264 Stream << "Op" << OperandIndex;
Guillaume Chatelet9b592382018-10-10 14:57:32 +0000265 IsFirst = false;
266 }
267 Stream << "]";
Guillaume Chatelet547d2dd2018-10-09 14:51:29 +0000268 Stream << "\n";
269 }
270 if (hasMemoryOperands())
271 Stream << "- hasMemoryOperands\n";
272 if (hasAliasingImplicitRegisters())
273 Stream << "- hasAliasingImplicitRegisters (execution is always serial)\n";
274 if (hasTiedRegisters())
275 Stream << "- hasTiedRegisters (execution is always serial)\n";
Clement Courbet8ef97e12019-09-27 08:04:10 +0000276 if (hasAliasingRegisters(RATC.emptyRegisters()))
Guillaume Chatelet547d2dd2018-10-09 14:51:29 +0000277 Stream << "- hasAliasingRegisters\n";
278}
279
Clement Courbet50cdd562019-10-09 11:58:42 +0000280InstructionsCache::InstructionsCache(const MCInstrInfo &InstrInfo,
Guillaume Chateletda11b852018-10-24 11:55:06 +0000281 const RegisterAliasingTrackerCache &RATC)
282 : InstrInfo(InstrInfo), RATC(RATC) {}
283
284const Instruction &InstructionsCache::getInstr(unsigned Opcode) const {
285 auto &Found = Instructions[Opcode];
286 if (!Found)
287 Found.reset(new Instruction(InstrInfo, RATC, Opcode));
288 return *Found;
289}
290
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000291bool RegisterOperandAssignment::
292operator==(const RegisterOperandAssignment &Other) const {
293 return std::tie(Op, Reg) == std::tie(Other.Op, Other.Reg);
294}
295
296bool AliasingRegisterOperands::
297operator==(const AliasingRegisterOperands &Other) const {
298 return std::tie(Defs, Uses) == std::tie(Other.Defs, Other.Uses);
299}
300
Clement Courbet50cdd562019-10-09 11:58:42 +0000301static void
302addOperandIfAlias(const MCPhysReg Reg, bool SelectDef,
303 ArrayRef<Operand> Operands,
304 SmallVectorImpl<RegisterOperandAssignment> &OperandValues) {
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000305 for (const auto &Op : Operands) {
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000306 if (Op.isReg() && Op.isDef() == SelectDef) {
307 const int SourceReg = Op.getRegisterAliasing().getOrigin(Reg);
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000308 if (SourceReg >= 0)
309 OperandValues.emplace_back(&Op, SourceReg);
310 }
311 }
312}
313
314bool AliasingRegisterOperands::hasImplicitAliasing() const {
315 const auto HasImplicit = [](const RegisterOperandAssignment &ROV) {
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000316 return ROV.Op->isImplicit();
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000317 };
Clement Courbet50cdd562019-10-09 11:58:42 +0000318 return any_of(Defs, HasImplicit) && any_of(Uses, HasImplicit);
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000319}
320
321bool AliasingConfigurations::empty() const { return Configurations.empty(); }
322
323bool AliasingConfigurations::hasImplicitAliasing() const {
Clement Courbet50cdd562019-10-09 11:58:42 +0000324 return any_of(Configurations, [](const AliasingRegisterOperands &ARO) {
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000325 return ARO.hasImplicitAliasing();
326 });
327}
328
329AliasingConfigurations::AliasingConfigurations(
Guillaume Chateletfcbb6f32018-10-17 11:37:28 +0000330 const Instruction &DefInstruction, const Instruction &UseInstruction) {
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000331 if (UseInstruction.AllUseRegs.anyCommon(DefInstruction.AllDefRegs)) {
332 auto CommonRegisters = UseInstruction.AllUseRegs;
333 CommonRegisters &= DefInstruction.AllDefRegs;
Clement Courbet50cdd562019-10-09 11:58:42 +0000334 for (const MCPhysReg Reg : CommonRegisters.set_bits()) {
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000335 AliasingRegisterOperands ARO;
336 addOperandIfAlias(Reg, true, DefInstruction.Operands, ARO.Defs);
337 addOperandIfAlias(Reg, false, UseInstruction.Operands, ARO.Uses);
338 if (!ARO.Defs.empty() && !ARO.Uses.empty() &&
Clement Courbet50cdd562019-10-09 11:58:42 +0000339 !is_contained(Configurations, ARO))
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000340 Configurations.push_back(std::move(ARO));
341 }
342 }
343}
344
Clement Courbet50cdd562019-10-09 11:58:42 +0000345void DumpMCOperand(const MCRegisterInfo &MCRegisterInfo, const MCOperand &Op,
346 raw_ostream &OS) {
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000347 if (!Op.isValid())
348 OS << "Invalid";
349 else if (Op.isReg())
350 OS << MCRegisterInfo.getName(Op.getReg());
351 else if (Op.isImm())
352 OS << Op.getImm();
353 else if (Op.isFPImm())
354 OS << Op.getFPImm();
355 else if (Op.isExpr())
356 OS << "Expr";
357 else if (Op.isInst())
358 OS << "SubInst";
359}
360
Clement Courbet50cdd562019-10-09 11:58:42 +0000361void DumpMCInst(const MCRegisterInfo &MCRegisterInfo,
362 const MCInstrInfo &MCInstrInfo, const MCInst &MCInst,
363 raw_ostream &OS) {
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000364 OS << MCInstrInfo.getName(MCInst.getOpcode());
365 for (unsigned I = 0, E = MCInst.getNumOperands(); I < E; ++I) {
366 if (I > 0)
367 OS << ',';
368 OS << ' ';
369 DumpMCOperand(MCRegisterInfo, MCInst.getOperand(I), OS);
370 }
371}
372
373} // namespace exegesis
Fangrui Song32401af2018-10-22 17:10:47 +0000374} // namespace llvm