1 //===-- MCInstrDescView.cpp -------------------------------------*- C++ -*-===//
3 // 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
7 //===----------------------------------------------------------------------===//
9 #include "MCInstrDescView.h"
15 #include "llvm/ADT/STLExtras.h"
20 unsigned Variable::getIndex() const {
21 assert(Index
>= 0 && "Index must be set");
25 unsigned Variable::getPrimaryOperandIndex() const {
26 assert(!TiedOperands
.empty());
27 return TiedOperands
[0];
30 bool 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;
39 unsigned Operand::getIndex() const {
40 assert(Index
>= 0 && "Index must be set");
44 bool Operand::isExplicit() const { return Info
; }
46 bool Operand::isImplicit() const { return !Info
; }
48 bool Operand::isImplicitReg() const { return ImplicitReg
; }
50 bool Operand::isDef() const { return IsDef
; }
52 bool Operand::isUse() const { return !IsDef
; }
54 bool Operand::isReg() const { return Tracker
; }
56 bool Operand::isTied() const { return TiedToIndex
>= 0; }
58 bool Operand::isVariable() const { return VariableIndex
>= 0; }
60 bool Operand::isMemory() const {
61 return isExplicit() &&
62 getExplicitOperandInfo().OperandType
== llvm::MCOI::OPERAND_MEMORY
;
65 bool Operand::isImmediate() const {
66 return isExplicit() &&
67 getExplicitOperandInfo().OperandType
== llvm::MCOI::OPERAND_IMMEDIATE
;
70 unsigned Operand::getTiedToIndex() const {
71 assert(isTied() && "Operand must be tied to get the tied index");
72 assert(TiedToIndex
>= 0 && "TiedToIndex must be set");
76 unsigned Operand::getVariableIndex() const {
77 assert(isVariable() && "Operand must be variable to get the Variable index");
78 assert(VariableIndex
>= 0 && "VariableIndex must be set");
82 unsigned Operand::getImplicitReg() const {
87 const RegisterAliasingTracker
&Operand::getRegisterAliasing() const {
92 const llvm::MCOperandInfo
&Operand::getExplicitOperandInfo() const {
97 Instruction::Instruction(const llvm::MCInstrInfo
&InstrInfo
,
98 const RegisterAliasingTrackerCache
&RATC
,
100 : Description(&InstrInfo
.get(Opcode
)), Name(InstrInfo
.getName(Opcode
)) {
101 unsigned OpIndex
= 0;
102 for (; OpIndex
< Description
->getNumOperands(); ++OpIndex
) {
103 const auto &OpInfo
= Description
->opInfo_begin()[OpIndex
];
105 Operand
.Index
= OpIndex
;
106 Operand
.IsDef
= (OpIndex
< Description
->getNumDefs());
107 // TODO(gchatelet): Handle isLookupPtrRegClass.
108 if (OpInfo
.RegClass
>= 0)
109 Operand
.Tracker
= &RATC
.getRegisterClass(OpInfo
.RegClass
);
110 Operand
.TiedToIndex
=
111 Description
->getOperandConstraint(OpIndex
, llvm::MCOI::TIED_TO
);
112 Operand
.Info
= &OpInfo
;
113 Operands
.push_back(Operand
);
115 for (const llvm::MCPhysReg
*MCPhysReg
= Description
->getImplicitDefs();
116 MCPhysReg
&& *MCPhysReg
; ++MCPhysReg
, ++OpIndex
) {
118 Operand
.Index
= OpIndex
;
119 Operand
.IsDef
= true;
120 Operand
.Tracker
= &RATC
.getRegister(*MCPhysReg
);
121 Operand
.ImplicitReg
= MCPhysReg
;
122 Operands
.push_back(Operand
);
124 for (const llvm::MCPhysReg
*MCPhysReg
= Description
->getImplicitUses();
125 MCPhysReg
&& *MCPhysReg
; ++MCPhysReg
, ++OpIndex
) {
127 Operand
.Index
= OpIndex
;
128 Operand
.IsDef
= false;
129 Operand
.Tracker
= &RATC
.getRegister(*MCPhysReg
);
130 Operand
.ImplicitReg
= MCPhysReg
;
131 Operands
.push_back(Operand
);
133 // Assigning Variables to non tied explicit operands.
134 Variables
.reserve(Operands
.size()); // Variables.size() <= Operands.size()
135 for (auto &Op
: Operands
)
136 if (Op
.isExplicit() && !Op
.isTied()) {
137 const size_t VariableIndex
= Variables
.size();
138 Op
.VariableIndex
= VariableIndex
;
139 Variables
.emplace_back();
140 Variables
.back().Index
= VariableIndex
;
142 // Assigning Variables to tied operands.
143 for (auto &Op
: Operands
)
145 Op
.VariableIndex
= Operands
[Op
.getTiedToIndex()].getVariableIndex();
146 // Assigning Operands to Variables.
147 for (auto &Op
: Operands
)
149 Variables
[Op
.getVariableIndex()].TiedOperands
.push_back(Op
.getIndex());
150 // Processing Aliasing.
151 ImplDefRegs
= RATC
.emptyRegisters();
152 ImplUseRegs
= RATC
.emptyRegisters();
153 AllDefRegs
= RATC
.emptyRegisters();
154 AllUseRegs
= RATC
.emptyRegisters();
155 for (const auto &Op
: Operands
) {
157 const auto &AliasingBits
= Op
.getRegisterAliasing().aliasedBits();
159 AllDefRegs
|= AliasingBits
;
161 AllUseRegs
|= AliasingBits
;
162 if (Op
.isDef() && Op
.isImplicit())
163 ImplDefRegs
|= AliasingBits
;
164 if (Op
.isUse() && Op
.isImplicit())
165 ImplUseRegs
|= AliasingBits
;
170 const Operand
&Instruction::getPrimaryOperand(const Variable
&Var
) const {
171 const auto PrimaryOperandIndex
= Var
.getPrimaryOperandIndex();
172 assert(PrimaryOperandIndex
< Operands
.size());
173 return Operands
[PrimaryOperandIndex
];
176 bool Instruction::hasMemoryOperands() const {
177 return any_of(Operands
, [](const Operand
&Op
) {
178 return Op
.isReg() && Op
.isExplicit() && Op
.isMemory();
182 bool Instruction::hasAliasingImplicitRegisters() const {
183 return ImplDefRegs
.anyCommon(ImplUseRegs
);
186 bool Instruction::hasAliasingImplicitRegistersThrough(
187 const Instruction
&OtherInstr
) const {
188 return ImplDefRegs
.anyCommon(OtherInstr
.ImplUseRegs
) &&
189 OtherInstr
.ImplDefRegs
.anyCommon(ImplUseRegs
);
192 bool Instruction::hasAliasingRegistersThrough(
193 const Instruction
&OtherInstr
) const {
194 return AllDefRegs
.anyCommon(OtherInstr
.AllUseRegs
) &&
195 OtherInstr
.AllDefRegs
.anyCommon(AllUseRegs
);
198 bool Instruction::hasTiedRegisters() const {
200 Variables
, [](const Variable
&Var
) { return Var
.hasTiedOperands(); });
203 bool Instruction::hasAliasingRegisters() const {
204 return AllDefRegs
.anyCommon(AllUseRegs
);
207 bool Instruction::hasOneUseOrOneDef() const {
208 return AllDefRegs
.count() || AllUseRegs
.count();
211 void Instruction::dump(const llvm::MCRegisterInfo
&RegInfo
,
212 llvm::raw_ostream
&Stream
) const {
213 Stream
<< "- " << Name
<< "\n";
214 for (const auto &Op
: Operands
) {
215 Stream
<< "- Op" << Op
.getIndex();
217 Stream
<< " Explicit";
219 Stream
<< " Implicit";
224 if (Op
.isImmediate())
225 Stream
<< " Immediate";
229 if (Op
.isImplicitReg())
230 Stream
<< " Reg(" << RegInfo
.getName(Op
.getImplicitReg()) << ")";
232 Stream
<< " RegClass("
233 << RegInfo
.getRegClassName(
234 &RegInfo
.getRegClass(Op
.Info
->RegClass
))
238 Stream
<< " TiedToOp" << Op
.getTiedToIndex();
241 for (const auto &Var
: Variables
) {
242 Stream
<< "- Var" << Var
.getIndex();
245 for (auto OperandIndex
: Var
.TiedOperands
) {
248 Stream
<< "Op" << OperandIndex
;
254 if (hasMemoryOperands())
255 Stream
<< "- hasMemoryOperands\n";
256 if (hasAliasingImplicitRegisters())
257 Stream
<< "- hasAliasingImplicitRegisters (execution is always serial)\n";
258 if (hasTiedRegisters())
259 Stream
<< "- hasTiedRegisters (execution is always serial)\n";
260 if (hasAliasingRegisters())
261 Stream
<< "- hasAliasingRegisters\n";
264 InstructionsCache::InstructionsCache(const llvm::MCInstrInfo
&InstrInfo
,
265 const RegisterAliasingTrackerCache
&RATC
)
266 : InstrInfo(InstrInfo
), RATC(RATC
) {}
268 const Instruction
&InstructionsCache::getInstr(unsigned Opcode
) const {
269 auto &Found
= Instructions
[Opcode
];
271 Found
.reset(new Instruction(InstrInfo
, RATC
, Opcode
));
275 bool RegisterOperandAssignment::
276 operator==(const RegisterOperandAssignment
&Other
) const {
277 return std::tie(Op
, Reg
) == std::tie(Other
.Op
, Other
.Reg
);
280 bool AliasingRegisterOperands::
281 operator==(const AliasingRegisterOperands
&Other
) const {
282 return std::tie(Defs
, Uses
) == std::tie(Other
.Defs
, Other
.Uses
);
285 static void addOperandIfAlias(
286 const llvm::MCPhysReg Reg
, bool SelectDef
, llvm::ArrayRef
<Operand
> Operands
,
287 llvm::SmallVectorImpl
<RegisterOperandAssignment
> &OperandValues
) {
288 for (const auto &Op
: Operands
) {
289 if (Op
.isReg() && Op
.isDef() == SelectDef
) {
290 const int SourceReg
= Op
.getRegisterAliasing().getOrigin(Reg
);
292 OperandValues
.emplace_back(&Op
, SourceReg
);
297 bool AliasingRegisterOperands::hasImplicitAliasing() const {
298 const auto HasImplicit
= [](const RegisterOperandAssignment
&ROV
) {
299 return ROV
.Op
->isImplicit();
301 return llvm::any_of(Defs
, HasImplicit
) && llvm::any_of(Uses
, HasImplicit
);
304 bool AliasingConfigurations::empty() const { return Configurations
.empty(); }
306 bool AliasingConfigurations::hasImplicitAliasing() const {
307 return llvm::any_of(Configurations
, [](const AliasingRegisterOperands
&ARO
) {
308 return ARO
.hasImplicitAliasing();
312 AliasingConfigurations::AliasingConfigurations(
313 const Instruction
&DefInstruction
, const Instruction
&UseInstruction
) {
314 if (UseInstruction
.AllUseRegs
.anyCommon(DefInstruction
.AllDefRegs
)) {
315 auto CommonRegisters
= UseInstruction
.AllUseRegs
;
316 CommonRegisters
&= DefInstruction
.AllDefRegs
;
317 for (const llvm::MCPhysReg Reg
: CommonRegisters
.set_bits()) {
318 AliasingRegisterOperands ARO
;
319 addOperandIfAlias(Reg
, true, DefInstruction
.Operands
, ARO
.Defs
);
320 addOperandIfAlias(Reg
, false, UseInstruction
.Operands
, ARO
.Uses
);
321 if (!ARO
.Defs
.empty() && !ARO
.Uses
.empty() &&
322 !llvm::is_contained(Configurations
, ARO
))
323 Configurations
.push_back(std::move(ARO
));
328 void DumpMCOperand(const llvm::MCRegisterInfo
&MCRegisterInfo
,
329 const llvm::MCOperand
&Op
, llvm::raw_ostream
&OS
) {
333 OS
<< MCRegisterInfo
.getName(Op
.getReg());
336 else if (Op
.isFPImm())
338 else if (Op
.isExpr())
340 else if (Op
.isInst())
344 void DumpMCInst(const llvm::MCRegisterInfo
&MCRegisterInfo
,
345 const llvm::MCInstrInfo
&MCInstrInfo
,
346 const llvm::MCInst
&MCInst
, llvm::raw_ostream
&OS
) {
347 OS
<< MCInstrInfo
.getName(MCInst
.getOpcode());
348 for (unsigned I
= 0, E
= MCInst
.getNumOperands(); I
< E
; ++I
) {
352 DumpMCOperand(MCRegisterInfo
, MCInst
.getOperand(I
), OS
);
356 } // namespace exegesis