blob: 3f3b4f46ddad315ba1068f98c966a642d67caa38 [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
30bool Variable::hasTiedOperands() const { return TiedOperands.size() > 1; }
31
32bool Operand::getIndex() const { return Index; }
33
34bool Operand::isExplicit() const { return Info; }
35
36bool Operand::isImplicit() const { return !Info; }
37
38bool Operand::isImplicitReg() const { return ImplicitReg; }
39
40bool Operand::isDef() const { return IsDef; }
41
42bool Operand::isUse() const { return !IsDef; }
43
44bool Operand::isReg() const { return Tracker; }
45
46bool Operand::isTied() const { return TiedToIndex >= 0; }
47
48bool Operand::isVariable() const { return VariableIndex >= 0; }
49
50bool Operand::isMemory() const {
51 return isExplicit() &&
52 getExplicitOperandInfo().OperandType == llvm::MCOI::OPERAND_MEMORY;
53}
54
55bool Operand::isImmediate() const {
56 return isExplicit() &&
57 getExplicitOperandInfo().OperandType == llvm::MCOI::OPERAND_IMMEDIATE;
58}
59
60int Operand::getTiedToIndex() const {
61 assert(isTied());
62 return TiedToIndex;
63}
64
65int Operand::getVariableIndex() const {
66 assert(isVariable());
67 return VariableIndex;
68}
69
70unsigned Operand::getImplicitReg() const {
71 assert(ImplicitReg);
72 return *ImplicitReg;
73}
74
75const RegisterAliasingTracker &Operand::getRegisterAliasing() const {
76 assert(Tracker);
77 return *Tracker;
78}
79
80const llvm::MCOperandInfo &Operand::getExplicitOperandInfo() const {
81 assert(Info);
82 return *Info;
83}
84
Clement Courbet0e69e2d2018-05-17 10:52:18 +000085Instruction::Instruction(const llvm::MCInstrDesc &MCInstrDesc,
Guillaume Chateletc9f727b2018-06-13 13:24:41 +000086 const RegisterAliasingTrackerCache &RATC)
Guillaume Chateletef6cef52018-06-20 08:52:30 +000087 : Description(&MCInstrDesc) {
Clement Courbet0e69e2d2018-05-17 10:52:18 +000088 unsigned OpIndex = 0;
89 for (; OpIndex < MCInstrDesc.getNumOperands(); ++OpIndex) {
90 const auto &OpInfo = MCInstrDesc.opInfo_begin()[OpIndex];
91 Operand Operand;
92 Operand.Index = OpIndex;
93 Operand.IsDef = (OpIndex < MCInstrDesc.getNumDefs());
Clement Courbet0e69e2d2018-05-17 10:52:18 +000094 // TODO(gchatelet): Handle isLookupPtrRegClass.
95 if (OpInfo.RegClass >= 0)
96 Operand.Tracker = &RATC.getRegisterClass(OpInfo.RegClass);
Guillaume Chateletc9f727b2018-06-13 13:24:41 +000097 Operand.TiedToIndex =
98 MCInstrDesc.getOperandConstraint(OpIndex, llvm::MCOI::TIED_TO);
Clement Courbet0e69e2d2018-05-17 10:52:18 +000099 Operand.Info = &OpInfo;
100 Operands.push_back(Operand);
101 }
102 for (const llvm::MCPhysReg *MCPhysReg = MCInstrDesc.getImplicitDefs();
103 MCPhysReg && *MCPhysReg; ++MCPhysReg, ++OpIndex) {
104 Operand Operand;
105 Operand.Index = OpIndex;
106 Operand.IsDef = true;
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000107 Operand.Tracker = &RATC.getRegister(*MCPhysReg);
108 Operand.ImplicitReg = MCPhysReg;
109 Operands.push_back(Operand);
110 }
111 for (const llvm::MCPhysReg *MCPhysReg = MCInstrDesc.getImplicitUses();
112 MCPhysReg && *MCPhysReg; ++MCPhysReg, ++OpIndex) {
113 Operand Operand;
114 Operand.Index = OpIndex;
115 Operand.IsDef = false;
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000116 Operand.Tracker = &RATC.getRegister(*MCPhysReg);
117 Operand.ImplicitReg = MCPhysReg;
118 Operands.push_back(Operand);
119 }
Guillaume Chateletc9f727b2018-06-13 13:24:41 +0000120 // Assigning Variables to non tied explicit operands.
121 Variables.reserve(Operands.size()); // Variables.size() <= Operands.size()
122 for (auto &Op : Operands)
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000123 if (Op.isExplicit() && !Op.isTied()) {
Guillaume Chateletc9f727b2018-06-13 13:24:41 +0000124 const size_t VariableIndex = Variables.size();
125 Op.VariableIndex = VariableIndex;
126 Variables.emplace_back();
127 Variables.back().Index = VariableIndex;
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000128 }
Guillaume Chateletc9f727b2018-06-13 13:24:41 +0000129 // Assigning Variables to tied operands.
130 for (auto &Op : Operands)
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000131 if (Op.isTied())
132 Op.VariableIndex = Operands[Op.getTiedToIndex()].getVariableIndex();
Guillaume Chateletc9f727b2018-06-13 13:24:41 +0000133 // Assigning Operands to Variables.
134 for (auto &Op : Operands)
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000135 if (Op.isVariable())
136 Variables[Op.getVariableIndex()].TiedOperands.push_back(Op.getIndex());
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000137 // Processing Aliasing.
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000138 ImplDefRegs = RATC.emptyRegisters();
139 ImplUseRegs = RATC.emptyRegisters();
140 AllDefRegs = RATC.emptyRegisters();
141 AllUseRegs = RATC.emptyRegisters();
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000142 for (const auto &Op : Operands) {
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000143 if (Op.isReg()) {
144 const auto &AliasingBits = Op.getRegisterAliasing().aliasedBits();
145 if (Op.isDef())
146 AllDefRegs |= AliasingBits;
147 if (Op.isUse())
148 AllUseRegs |= AliasingBits;
149 if (Op.isDef() && Op.isImplicit())
150 ImplDefRegs |= AliasingBits;
151 if (Op.isUse() && Op.isImplicit())
152 ImplUseRegs |= AliasingBits;
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000153 }
154 }
155}
156
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000157const Operand &Instruction::getPrimaryOperand(const Variable &Var) const {
158 const auto PrimaryOperandIndex = Var.getPrimaryOperandIndex();
159 assert(PrimaryOperandIndex < Operands.size());
160 return Operands[PrimaryOperandIndex];
161}
162
Guillaume Chateletfb943542018-08-01 14:41:45 +0000163bool Instruction::hasMemoryOperands() const {
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000164 return std::any_of(Operands.begin(), Operands.end(), [](const Operand &Op) {
165 return Op.isReg() && Op.isExplicit() && Op.isMemory();
166 });
167}
168
169bool Instruction::hasAliasingImplicitRegisters() const {
170 return ImplDefRegs.anyCommon(ImplUseRegs);
171}
172
173bool Instruction::hasTiedRegisters() const {
174 return llvm::any_of(
Guillaume Chateletcf6d5fa2018-10-09 09:33:29 +0000175 Variables, [](const Variable &Var) { return Var.hasTiedOperands(); });
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000176}
177
178bool Instruction::hasAliasingRegisters() const {
179 return AllDefRegs.anyCommon(AllUseRegs);
Guillaume Chateletfb943542018-08-01 14:41:45 +0000180}
181
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000182bool RegisterOperandAssignment::
183operator==(const RegisterOperandAssignment &Other) const {
184 return std::tie(Op, Reg) == std::tie(Other.Op, Other.Reg);
185}
186
187bool AliasingRegisterOperands::
188operator==(const AliasingRegisterOperands &Other) const {
189 return std::tie(Defs, Uses) == std::tie(Other.Defs, Other.Uses);
190}
191
192static void addOperandIfAlias(
193 const llvm::MCPhysReg Reg, bool SelectDef, llvm::ArrayRef<Operand> Operands,
194 llvm::SmallVectorImpl<RegisterOperandAssignment> &OperandValues) {
195 for (const auto &Op : Operands) {
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000196 if (Op.isReg() && Op.isDef() == SelectDef) {
197 const int SourceReg = Op.getRegisterAliasing().getOrigin(Reg);
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000198 if (SourceReg >= 0)
199 OperandValues.emplace_back(&Op, SourceReg);
200 }
201 }
202}
203
204bool AliasingRegisterOperands::hasImplicitAliasing() const {
205 const auto HasImplicit = [](const RegisterOperandAssignment &ROV) {
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000206 return ROV.Op->isImplicit();
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000207 };
208 return llvm::any_of(Defs, HasImplicit) && llvm::any_of(Uses, HasImplicit);
209}
210
211bool AliasingConfigurations::empty() const { return Configurations.empty(); }
212
213bool AliasingConfigurations::hasImplicitAliasing() const {
214 return llvm::any_of(Configurations, [](const AliasingRegisterOperands &ARO) {
215 return ARO.hasImplicitAliasing();
216 });
217}
218
219AliasingConfigurations::AliasingConfigurations(
220 const Instruction &DefInstruction, const Instruction &UseInstruction)
221 : DefInstruction(DefInstruction), UseInstruction(UseInstruction) {
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000222 if (UseInstruction.AllUseRegs.anyCommon(DefInstruction.AllDefRegs)) {
223 auto CommonRegisters = UseInstruction.AllUseRegs;
224 CommonRegisters &= DefInstruction.AllDefRegs;
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000225 for (const llvm::MCPhysReg Reg : CommonRegisters.set_bits()) {
226 AliasingRegisterOperands ARO;
227 addOperandIfAlias(Reg, true, DefInstruction.Operands, ARO.Defs);
228 addOperandIfAlias(Reg, false, UseInstruction.Operands, ARO.Uses);
229 if (!ARO.Defs.empty() && !ARO.Uses.empty() &&
230 !llvm::is_contained(Configurations, ARO))
231 Configurations.push_back(std::move(ARO));
232 }
233 }
234}
235
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000236void DumpMCOperand(const llvm::MCRegisterInfo &MCRegisterInfo,
237 const llvm::MCOperand &Op, llvm::raw_ostream &OS) {
238 if (!Op.isValid())
239 OS << "Invalid";
240 else if (Op.isReg())
241 OS << MCRegisterInfo.getName(Op.getReg());
242 else if (Op.isImm())
243 OS << Op.getImm();
244 else if (Op.isFPImm())
245 OS << Op.getFPImm();
246 else if (Op.isExpr())
247 OS << "Expr";
248 else if (Op.isInst())
249 OS << "SubInst";
250}
251
252void DumpMCInst(const llvm::MCRegisterInfo &MCRegisterInfo,
253 const llvm::MCInstrInfo &MCInstrInfo,
254 const llvm::MCInst &MCInst, llvm::raw_ostream &OS) {
255 OS << MCInstrInfo.getName(MCInst.getOpcode());
256 for (unsigned I = 0, E = MCInst.getNumOperands(); I < E; ++I) {
257 if (I > 0)
258 OS << ',';
259 OS << ' ';
260 DumpMCOperand(MCRegisterInfo, MCInst.getOperand(I), OS);
261 }
262}
263
264} // namespace exegesis