blob: c7cd85c1f78010cce536cc6aca409c9b5cd0e035 [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
Clement Courbet0e69e2d2018-05-17 10:52:18 +000020Instruction::Instruction(const llvm::MCInstrDesc &MCInstrDesc,
Guillaume Chateletc9f727b2018-06-13 13:24:41 +000021 const RegisterAliasingTrackerCache &RATC)
Guillaume Chateletef6cef52018-06-20 08:52:30 +000022 : Description(&MCInstrDesc) {
Clement Courbet0e69e2d2018-05-17 10:52:18 +000023 unsigned OpIndex = 0;
24 for (; OpIndex < MCInstrDesc.getNumOperands(); ++OpIndex) {
25 const auto &OpInfo = MCInstrDesc.opInfo_begin()[OpIndex];
26 Operand Operand;
27 Operand.Index = OpIndex;
28 Operand.IsDef = (OpIndex < MCInstrDesc.getNumDefs());
Guillaume Chateletfb943542018-08-01 14:41:45 +000029 Operand.IsMem = OpInfo.OperandType == llvm::MCOI::OPERAND_MEMORY;
Clement Courbet0e69e2d2018-05-17 10:52:18 +000030 Operand.IsExplicit = true;
31 // TODO(gchatelet): Handle isLookupPtrRegClass.
32 if (OpInfo.RegClass >= 0)
33 Operand.Tracker = &RATC.getRegisterClass(OpInfo.RegClass);
Guillaume Chateletc9f727b2018-06-13 13:24:41 +000034 Operand.TiedToIndex =
35 MCInstrDesc.getOperandConstraint(OpIndex, llvm::MCOI::TIED_TO);
Clement Courbet0e69e2d2018-05-17 10:52:18 +000036 Operand.Info = &OpInfo;
37 Operands.push_back(Operand);
38 }
39 for (const llvm::MCPhysReg *MCPhysReg = MCInstrDesc.getImplicitDefs();
40 MCPhysReg && *MCPhysReg; ++MCPhysReg, ++OpIndex) {
41 Operand Operand;
42 Operand.Index = OpIndex;
43 Operand.IsDef = true;
44 Operand.IsExplicit = false;
45 Operand.Tracker = &RATC.getRegister(*MCPhysReg);
46 Operand.ImplicitReg = MCPhysReg;
47 Operands.push_back(Operand);
48 }
49 for (const llvm::MCPhysReg *MCPhysReg = MCInstrDesc.getImplicitUses();
50 MCPhysReg && *MCPhysReg; ++MCPhysReg, ++OpIndex) {
51 Operand Operand;
52 Operand.Index = OpIndex;
53 Operand.IsDef = false;
54 Operand.IsExplicit = false;
55 Operand.Tracker = &RATC.getRegister(*MCPhysReg);
56 Operand.ImplicitReg = MCPhysReg;
57 Operands.push_back(Operand);
58 }
Guillaume Chateletc9f727b2018-06-13 13:24:41 +000059 // Assigning Variables to non tied explicit operands.
60 Variables.reserve(Operands.size()); // Variables.size() <= Operands.size()
61 for (auto &Op : Operands)
62 if (Op.IsExplicit && Op.TiedToIndex < 0) {
63 const size_t VariableIndex = Variables.size();
64 Op.VariableIndex = VariableIndex;
65 Variables.emplace_back();
66 Variables.back().Index = VariableIndex;
Clement Courbet0e69e2d2018-05-17 10:52:18 +000067 }
Guillaume Chateletc9f727b2018-06-13 13:24:41 +000068 // Assigning Variables to tied operands.
69 for (auto &Op : Operands)
70 if (Op.TiedToIndex >= 0)
71 Op.VariableIndex = Operands[Op.TiedToIndex].VariableIndex;
72 // Assigning Operands to Variables.
73 for (auto &Op : Operands)
74 if (Op.VariableIndex >= 0)
Guillaume Chateletef6cef52018-06-20 08:52:30 +000075 Variables[Op.VariableIndex].TiedOperands.push_back(Op.Index);
Clement Courbet0e69e2d2018-05-17 10:52:18 +000076 // Processing Aliasing.
77 DefRegisters = RATC.emptyRegisters();
78 UseRegisters = RATC.emptyRegisters();
79 for (const auto &Op : Operands) {
80 if (Op.Tracker) {
81 auto &Registers = Op.IsDef ? DefRegisters : UseRegisters;
82 Registers |= Op.Tracker->aliasedBits();
83 }
84 }
85}
86
Guillaume Chateletfb943542018-08-01 14:41:45 +000087bool Instruction::hasMemoryOperands() const {
88 return std::any_of(Operands.begin(), Operands.end(),
89 [](const Operand &Op) { return Op.IsMem; });
90}
91
Clement Courbet0e69e2d2018-05-17 10:52:18 +000092bool RegisterOperandAssignment::
93operator==(const RegisterOperandAssignment &Other) const {
94 return std::tie(Op, Reg) == std::tie(Other.Op, Other.Reg);
95}
96
97bool AliasingRegisterOperands::
98operator==(const AliasingRegisterOperands &Other) const {
99 return std::tie(Defs, Uses) == std::tie(Other.Defs, Other.Uses);
100}
101
102static void addOperandIfAlias(
103 const llvm::MCPhysReg Reg, bool SelectDef, llvm::ArrayRef<Operand> Operands,
104 llvm::SmallVectorImpl<RegisterOperandAssignment> &OperandValues) {
105 for (const auto &Op : Operands) {
106 if (Op.Tracker && Op.IsDef == SelectDef) {
107 const int SourceReg = Op.Tracker->getOrigin(Reg);
108 if (SourceReg >= 0)
109 OperandValues.emplace_back(&Op, SourceReg);
110 }
111 }
112}
113
114bool AliasingRegisterOperands::hasImplicitAliasing() const {
115 const auto HasImplicit = [](const RegisterOperandAssignment &ROV) {
116 return !ROV.Op->IsExplicit;
117 };
118 return llvm::any_of(Defs, HasImplicit) && llvm::any_of(Uses, HasImplicit);
119}
120
121bool AliasingConfigurations::empty() const { return Configurations.empty(); }
122
123bool AliasingConfigurations::hasImplicitAliasing() const {
124 return llvm::any_of(Configurations, [](const AliasingRegisterOperands &ARO) {
125 return ARO.hasImplicitAliasing();
126 });
127}
128
129AliasingConfigurations::AliasingConfigurations(
130 const Instruction &DefInstruction, const Instruction &UseInstruction)
131 : DefInstruction(DefInstruction), UseInstruction(UseInstruction) {
132 if (UseInstruction.UseRegisters.anyCommon(DefInstruction.DefRegisters)) {
133 auto CommonRegisters = UseInstruction.UseRegisters;
134 CommonRegisters &= DefInstruction.DefRegisters;
135 for (const llvm::MCPhysReg Reg : CommonRegisters.set_bits()) {
136 AliasingRegisterOperands ARO;
137 addOperandIfAlias(Reg, true, DefInstruction.Operands, ARO.Defs);
138 addOperandIfAlias(Reg, false, UseInstruction.Operands, ARO.Uses);
139 if (!ARO.Defs.empty() && !ARO.Uses.empty() &&
140 !llvm::is_contained(Configurations, ARO))
141 Configurations.push_back(std::move(ARO));
142 }
143 }
144}
145
Clement Courbet0e69e2d2018-05-17 10:52:18 +0000146void DumpMCOperand(const llvm::MCRegisterInfo &MCRegisterInfo,
147 const llvm::MCOperand &Op, llvm::raw_ostream &OS) {
148 if (!Op.isValid())
149 OS << "Invalid";
150 else if (Op.isReg())
151 OS << MCRegisterInfo.getName(Op.getReg());
152 else if (Op.isImm())
153 OS << Op.getImm();
154 else if (Op.isFPImm())
155 OS << Op.getFPImm();
156 else if (Op.isExpr())
157 OS << "Expr";
158 else if (Op.isInst())
159 OS << "SubInst";
160}
161
162void DumpMCInst(const llvm::MCRegisterInfo &MCRegisterInfo,
163 const llvm::MCInstrInfo &MCInstrInfo,
164 const llvm::MCInst &MCInst, llvm::raw_ostream &OS) {
165 OS << MCInstrInfo.getName(MCInst.getOpcode());
166 for (unsigned I = 0, E = MCInst.getNumOperands(); I < E; ++I) {
167 if (I > 0)
168 OS << ',';
169 OS << ' ';
170 DumpMCOperand(MCRegisterInfo, MCInst.getOperand(I), OS);
171 }
172}
173
174} // namespace exegesis