blob: f2007afc9374e65b58e17640d4429eceea898fe0 [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 {
21 assert(Index >= 0);
22 return Index;
23}
24unsigned Variable::getPrimaryOperandIndex() const {
25 assert(!TiedOperands.empty());
26 return TiedOperands[0];
27}
28
29bool Variable::hasTiedOperands() const { return TiedOperands.size() > 1; }
30
31bool Operand::getIndex() const { return Index; }
32
33bool Operand::isExplicit() const { return Info; }
34
35bool Operand::isImplicit() const { return !Info; }
36
37bool Operand::isImplicitReg() const { return ImplicitReg; }
38
39bool Operand::isDef() const { return IsDef; }
40
41bool Operand::isUse() const { return !IsDef; }
42
43bool Operand::isReg() const { return Tracker; }
44
45bool Operand::isTied() const { return TiedToIndex >= 0; }
46
47bool Operand::isVariable() const { return VariableIndex >= 0; }
48
49bool Operand::isMemory() const {
50 return isExplicit() &&
51 getExplicitOperandInfo().OperandType == llvm::MCOI::OPERAND_MEMORY;
52}
53
54bool Operand::isImmediate() const {
55 return isExplicit() &&
56 getExplicitOperandInfo().OperandType == llvm::MCOI::OPERAND_IMMEDIATE;
57}
58
59int Operand::getTiedToIndex() const {
60 assert(isTied());
61 return TiedToIndex;
62}
63
64int Operand::getVariableIndex() const {
65 assert(isVariable());
66 return VariableIndex;
67}
68
69unsigned Operand::getImplicitReg() const {
70 assert(ImplicitReg);
71 return *ImplicitReg;
72}
73
74const RegisterAliasingTracker &Operand::getRegisterAliasing() const {
75 assert(Tracker);
76 return *Tracker;
77}
78
79const llvm::MCOperandInfo &Operand::getExplicitOperandInfo() const {
80 assert(Info);
81 return *Info;
82}
83
Clement Courbet0e69e2d2018-05-17 10:52:18 +000084Instruction::Instruction(const llvm::MCInstrDesc &MCInstrDesc,
Guillaume Chateletc9f727b2018-06-13 13:24:41 +000085 const RegisterAliasingTrackerCache &RATC)
Guillaume Chateletef6cef52018-06-20 08:52:30 +000086 : Description(&MCInstrDesc) {
Clement Courbet0e69e2d2018-05-17 10:52:18 +000087 unsigned OpIndex = 0;
88 for (; OpIndex < MCInstrDesc.getNumOperands(); ++OpIndex) {
89 const auto &OpInfo = MCInstrDesc.opInfo_begin()[OpIndex];
90 Operand Operand;
91 Operand.Index = OpIndex;
92 Operand.IsDef = (OpIndex < MCInstrDesc.getNumDefs());
Clement Courbet0e69e2d2018-05-17 10:52:18 +000093 // TODO(gchatelet): Handle isLookupPtrRegClass.
94 if (OpInfo.RegClass >= 0)
95 Operand.Tracker = &RATC.getRegisterClass(OpInfo.RegClass);
Guillaume Chateletc9f727b2018-06-13 13:24:41 +000096 Operand.TiedToIndex =
97 MCInstrDesc.getOperandConstraint(OpIndex, llvm::MCOI::TIED_TO);
Clement Courbet0e69e2d2018-05-17 10:52:18 +000098 Operand.Info = &OpInfo;
99 Operands.push_back(Operand);
100 }
101 for (const llvm::MCPhysReg *MCPhysReg = MCInstrDesc.getImplicitDefs();
102 MCPhysReg && *MCPhysReg; ++MCPhysReg, ++OpIndex) {
103 Operand Operand;
104 Operand.Index = OpIndex;
105 Operand.IsDef = true;
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000106 Operand.Tracker = &RATC.getRegister(*MCPhysReg);
107 Operand.ImplicitReg = MCPhysReg;
108 Operands.push_back(Operand);
109 }
110 for (const llvm::MCPhysReg *MCPhysReg = MCInstrDesc.getImplicitUses();
111 MCPhysReg && *MCPhysReg; ++MCPhysReg, ++OpIndex) {
112 Operand Operand;
113 Operand.Index = OpIndex;
114 Operand.IsDef = false;
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000115 Operand.Tracker = &RATC.getRegister(*MCPhysReg);
116 Operand.ImplicitReg = MCPhysReg;
117 Operands.push_back(Operand);
118 }
Guillaume Chateletc9f727b2018-06-13 13:24:41 +0000119 // Assigning Variables to non tied explicit operands.
120 Variables.reserve(Operands.size()); // Variables.size() <= Operands.size()
121 for (auto &Op : Operands)
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000122 if (Op.isExplicit() && !Op.isTied()) {
Guillaume Chateletc9f727b2018-06-13 13:24:41 +0000123 const size_t VariableIndex = Variables.size();
124 Op.VariableIndex = VariableIndex;
125 Variables.emplace_back();
126 Variables.back().Index = VariableIndex;
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000127 }
Guillaume Chateletc9f727b2018-06-13 13:24:41 +0000128 // Assigning Variables to tied operands.
129 for (auto &Op : Operands)
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000130 if (Op.isTied())
131 Op.VariableIndex = Operands[Op.getTiedToIndex()].getVariableIndex();
Guillaume Chateletc9f727b2018-06-13 13:24:41 +0000132 // Assigning Operands to Variables.
133 for (auto &Op : Operands)
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000134 if (Op.isVariable())
135 Variables[Op.getVariableIndex()].TiedOperands.push_back(Op.getIndex());
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000136 // Processing Aliasing.
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000137 ImplDefRegs = RATC.emptyRegisters();
138 ImplUseRegs = RATC.emptyRegisters();
139 AllDefRegs = RATC.emptyRegisters();
140 AllUseRegs = RATC.emptyRegisters();
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000141 for (const auto &Op : Operands) {
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000142 if (Op.isReg()) {
143 const auto &AliasingBits = Op.getRegisterAliasing().aliasedBits();
144 if (Op.isDef())
145 AllDefRegs |= AliasingBits;
146 if (Op.isUse())
147 AllUseRegs |= AliasingBits;
148 if (Op.isDef() && Op.isImplicit())
149 ImplDefRegs |= AliasingBits;
150 if (Op.isUse() && Op.isImplicit())
151 ImplUseRegs |= AliasingBits;
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000152 }
153 }
154}
155
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000156const Operand &Instruction::getPrimaryOperand(const Variable &Var) const {
157 const auto PrimaryOperandIndex = Var.getPrimaryOperandIndex();
158 assert(PrimaryOperandIndex < Operands.size());
159 return Operands[PrimaryOperandIndex];
160}
161
Guillaume Chateletfb943542018-08-01 14:41:45 +0000162bool Instruction::hasMemoryOperands() const {
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000163 return std::any_of(Operands.begin(), Operands.end(), [](const Operand &Op) {
164 return Op.isReg() && Op.isExplicit() && Op.isMemory();
165 });
166}
167
168bool Instruction::hasAliasingImplicitRegisters() const {
169 return ImplDefRegs.anyCommon(ImplUseRegs);
170}
171
172bool Instruction::hasTiedRegisters() const {
173 return llvm::any_of(
174 Variables, [this](const Variable &Var) { return Var.hasTiedOperands(); });
175}
176
177bool Instruction::hasAliasingRegisters() const {
178 return AllDefRegs.anyCommon(AllUseRegs);
Guillaume Chateletfb943542018-08-01 14:41:45 +0000179}
180
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000181bool RegisterOperandAssignment::
182operator==(const RegisterOperandAssignment &Other) const {
183 return std::tie(Op, Reg) == std::tie(Other.Op, Other.Reg);
184}
185
186bool AliasingRegisterOperands::
187operator==(const AliasingRegisterOperands &Other) const {
188 return std::tie(Defs, Uses) == std::tie(Other.Defs, Other.Uses);
189}
190
191static void addOperandIfAlias(
192 const llvm::MCPhysReg Reg, bool SelectDef, llvm::ArrayRef<Operand> Operands,
193 llvm::SmallVectorImpl<RegisterOperandAssignment> &OperandValues) {
194 for (const auto &Op : Operands) {
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000195 if (Op.isReg() && Op.isDef() == SelectDef) {
196 const int SourceReg = Op.getRegisterAliasing().getOrigin(Reg);
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000197 if (SourceReg >= 0)
198 OperandValues.emplace_back(&Op, SourceReg);
199 }
200 }
201}
202
203bool AliasingRegisterOperands::hasImplicitAliasing() const {
204 const auto HasImplicit = [](const RegisterOperandAssignment &ROV) {
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000205 return ROV.Op->isImplicit();
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000206 };
207 return llvm::any_of(Defs, HasImplicit) && llvm::any_of(Uses, HasImplicit);
208}
209
210bool AliasingConfigurations::empty() const { return Configurations.empty(); }
211
212bool AliasingConfigurations::hasImplicitAliasing() const {
213 return llvm::any_of(Configurations, [](const AliasingRegisterOperands &ARO) {
214 return ARO.hasImplicitAliasing();
215 });
216}
217
218AliasingConfigurations::AliasingConfigurations(
219 const Instruction &DefInstruction, const Instruction &UseInstruction)
220 : DefInstruction(DefInstruction), UseInstruction(UseInstruction) {
Guillaume Chatelet09c28392018-10-09 08:59:10 +0000221 if (UseInstruction.AllUseRegs.anyCommon(DefInstruction.AllDefRegs)) {
222 auto CommonRegisters = UseInstruction.AllUseRegs;
223 CommonRegisters &= DefInstruction.AllDefRegs;
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000224 for (const llvm::MCPhysReg Reg : CommonRegisters.set_bits()) {
225 AliasingRegisterOperands ARO;
226 addOperandIfAlias(Reg, true, DefInstruction.Operands, ARO.Defs);
227 addOperandIfAlias(Reg, false, UseInstruction.Operands, ARO.Uses);
228 if (!ARO.Defs.empty() && !ARO.Uses.empty() &&
229 !llvm::is_contained(Configurations, ARO))
230 Configurations.push_back(std::move(ARO));
231 }
232 }
233}
234
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000235void DumpMCOperand(const llvm::MCRegisterInfo &MCRegisterInfo,
236 const llvm::MCOperand &Op, llvm::raw_ostream &OS) {
237 if (!Op.isValid())
238 OS << "Invalid";
239 else if (Op.isReg())
240 OS << MCRegisterInfo.getName(Op.getReg());
241 else if (Op.isImm())
242 OS << Op.getImm();
243 else if (Op.isFPImm())
244 OS << Op.getFPImm();
245 else if (Op.isExpr())
246 OS << "Expr";
247 else if (Op.isInst())
248 OS << "SubInst";
249}
250
251void DumpMCInst(const llvm::MCRegisterInfo &MCRegisterInfo,
252 const llvm::MCInstrInfo &MCInstrInfo,
253 const llvm::MCInst &MCInst, llvm::raw_ostream &OS) {
254 OS << MCInstrInfo.getName(MCInst.getOpcode());
255 for (unsigned I = 0, E = MCInst.getNumOperands(); I < E; ++I) {
256 if (I > 0)
257 OS << ',';
258 OS << ' ';
259 DumpMCOperand(MCRegisterInfo, MCInst.getOperand(I), OS);
260 }
261}
262
263} // namespace exegesis