aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/llvm12/tools/llvm-exegesis/lib/MCInstrDescView.cpp
diff options
context:
space:
mode:
authormonster <monster@ydb.tech>2022-07-07 14:41:37 +0300
committermonster <monster@ydb.tech>2022-07-07 14:41:37 +0300
commit06e5c21a835c0e923506c4ff27929f34e00761c2 (patch)
tree75efcbc6854ef9bd476eb8bf00cc5c900da436a2 /contrib/libs/llvm12/tools/llvm-exegesis/lib/MCInstrDescView.cpp
parent03f024c4412e3aa613bb543cf1660176320ba8f4 (diff)
downloadydb-06e5c21a835c0e923506c4ff27929f34e00761c2.tar.gz
fix ya.make
Diffstat (limited to 'contrib/libs/llvm12/tools/llvm-exegesis/lib/MCInstrDescView.cpp')
-rw-r--r--contrib/libs/llvm12/tools/llvm-exegesis/lib/MCInstrDescView.cpp398
1 files changed, 398 insertions, 0 deletions
diff --git a/contrib/libs/llvm12/tools/llvm-exegesis/lib/MCInstrDescView.cpp b/contrib/libs/llvm12/tools/llvm-exegesis/lib/MCInstrDescView.cpp
new file mode 100644
index 0000000000..674db3fe15
--- /dev/null
+++ b/contrib/libs/llvm12/tools/llvm-exegesis/lib/MCInstrDescView.cpp
@@ -0,0 +1,398 @@
+//===-- MCInstrDescView.cpp -------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "MCInstrDescView.h"
+
+#include <iterator>
+#include <map>
+#include <tuple>
+
+#include "llvm/ADT/STLExtras.h"
+
+namespace llvm {
+namespace exegesis {
+
+unsigned Variable::getIndex() const { return *Index; }
+
+unsigned Variable::getPrimaryOperandIndex() const {
+ assert(!TiedOperands.empty());
+ return TiedOperands[0];
+}
+
+bool Variable::hasTiedOperands() const {
+ assert(TiedOperands.size() <= 2 &&
+ "No more than two operands can be tied together");
+ // By definition only Use and Def operands can be tied together.
+ // TiedOperands[0] is the Def operand (LLVM stores defs first).
+ // TiedOperands[1] is the Use operand.
+ return TiedOperands.size() > 1;
+}
+
+unsigned Operand::getIndex() const { return *Index; }
+
+bool Operand::isExplicit() const { return Info; }
+
+bool Operand::isImplicit() const { return !Info; }
+
+bool Operand::isImplicitReg() const { return ImplicitReg; }
+
+bool Operand::isDef() const { return IsDef; }
+
+bool Operand::isUse() const { return !IsDef; }
+
+bool Operand::isReg() const { return Tracker; }
+
+bool Operand::isTied() const { return TiedToIndex.hasValue(); }
+
+bool Operand::isVariable() const { return VariableIndex.hasValue(); }
+
+bool Operand::isMemory() const {
+ return isExplicit() &&
+ getExplicitOperandInfo().OperandType == MCOI::OPERAND_MEMORY;
+}
+
+bool Operand::isImmediate() const {
+ return isExplicit() &&
+ getExplicitOperandInfo().OperandType == MCOI::OPERAND_IMMEDIATE;
+}
+
+unsigned Operand::getTiedToIndex() const { return *TiedToIndex; }
+
+unsigned Operand::getVariableIndex() const { return *VariableIndex; }
+
+unsigned Operand::getImplicitReg() const {
+ assert(ImplicitReg);
+ return *ImplicitReg;
+}
+
+const RegisterAliasingTracker &Operand::getRegisterAliasing() const {
+ assert(Tracker);
+ return *Tracker;
+}
+
+const MCOperandInfo &Operand::getExplicitOperandInfo() const {
+ assert(Info);
+ return *Info;
+}
+
+const BitVector *BitVectorCache::getUnique(BitVector &&BV) const {
+ for (const auto &Entry : Cache)
+ if (*Entry == BV)
+ return Entry.get();
+ Cache.push_back(std::make_unique<BitVector>());
+ auto &Entry = Cache.back();
+ Entry->swap(BV);
+ return Entry.get();
+}
+
+Instruction::Instruction(const MCInstrDesc *Description, StringRef Name,
+ SmallVector<Operand, 8> Operands,
+ SmallVector<Variable, 4> Variables,
+ const BitVector *ImplDefRegs,
+ const BitVector *ImplUseRegs,
+ const BitVector *AllDefRegs,
+ const BitVector *AllUseRegs)
+ : Description(*Description), Name(Name), Operands(std::move(Operands)),
+ Variables(std::move(Variables)), ImplDefRegs(*ImplDefRegs),
+ ImplUseRegs(*ImplUseRegs), AllDefRegs(*AllDefRegs),
+ AllUseRegs(*AllUseRegs) {}
+
+std::unique_ptr<Instruction>
+Instruction::create(const MCInstrInfo &InstrInfo,
+ const RegisterAliasingTrackerCache &RATC,
+ const BitVectorCache &BVC, unsigned Opcode) {
+ const llvm::MCInstrDesc *const Description = &InstrInfo.get(Opcode);
+ unsigned OpIndex = 0;
+ SmallVector<Operand, 8> Operands;
+ SmallVector<Variable, 4> Variables;
+ for (; OpIndex < Description->getNumOperands(); ++OpIndex) {
+ const auto &OpInfo = Description->opInfo_begin()[OpIndex];
+ Operand Operand;
+ Operand.Index = OpIndex;
+ Operand.IsDef = (OpIndex < Description->getNumDefs());
+ // TODO(gchatelet): Handle isLookupPtrRegClass.
+ if (OpInfo.RegClass >= 0)
+ Operand.Tracker = &RATC.getRegisterClass(OpInfo.RegClass);
+ int TiedToIndex = Description->getOperandConstraint(OpIndex, MCOI::TIED_TO);
+ assert((TiedToIndex == -1 ||
+ (0 <= TiedToIndex &&
+ TiedToIndex < std::numeric_limits<uint8_t>::max())) &&
+ "Unknown Operand Constraint");
+ if (TiedToIndex >= 0)
+ Operand.TiedToIndex = TiedToIndex;
+ Operand.Info = &OpInfo;
+ Operands.push_back(Operand);
+ }
+ for (const MCPhysReg *MCPhysReg = Description->getImplicitDefs();
+ MCPhysReg && *MCPhysReg; ++MCPhysReg, ++OpIndex) {
+ Operand Operand;
+ Operand.Index = OpIndex;
+ Operand.IsDef = true;
+ Operand.Tracker = &RATC.getRegister(*MCPhysReg);
+ Operand.ImplicitReg = MCPhysReg;
+ Operands.push_back(Operand);
+ }
+ for (const MCPhysReg *MCPhysReg = Description->getImplicitUses();
+ MCPhysReg && *MCPhysReg; ++MCPhysReg, ++OpIndex) {
+ Operand Operand;
+ Operand.Index = OpIndex;
+ Operand.IsDef = false;
+ Operand.Tracker = &RATC.getRegister(*MCPhysReg);
+ Operand.ImplicitReg = MCPhysReg;
+ Operands.push_back(Operand);
+ }
+ Variables.reserve(Operands.size()); // Variables.size() <= Operands.size()
+ // Assigning Variables to non tied explicit operands.
+ for (auto &Op : Operands)
+ if (Op.isExplicit() && !Op.isTied()) {
+ const size_t VariableIndex = Variables.size();
+ assert(VariableIndex < std::numeric_limits<uint8_t>::max());
+ Op.VariableIndex = VariableIndex;
+ Variables.emplace_back();
+ Variables.back().Index = VariableIndex;
+ }
+ // Assigning Variables to tied operands.
+ for (auto &Op : Operands)
+ if (Op.isExplicit() && Op.isTied())
+ Op.VariableIndex = Operands[Op.getTiedToIndex()].getVariableIndex();
+ // Assigning Operands to Variables.
+ for (auto &Op : Operands)
+ if (Op.isVariable())
+ Variables[Op.getVariableIndex()].TiedOperands.push_back(Op.getIndex());
+ // Processing Aliasing.
+ BitVector ImplDefRegs = RATC.emptyRegisters();
+ BitVector ImplUseRegs = RATC.emptyRegisters();
+ BitVector AllDefRegs = RATC.emptyRegisters();
+ BitVector AllUseRegs = RATC.emptyRegisters();
+ for (const auto &Op : Operands) {
+ if (Op.isReg()) {
+ const auto &AliasingBits = Op.getRegisterAliasing().aliasedBits();
+ if (Op.isDef())
+ AllDefRegs |= AliasingBits;
+ if (Op.isUse())
+ AllUseRegs |= AliasingBits;
+ if (Op.isDef() && Op.isImplicit())
+ ImplDefRegs |= AliasingBits;
+ if (Op.isUse() && Op.isImplicit())
+ ImplUseRegs |= AliasingBits;
+ }
+ }
+ // Can't use make_unique because constructor is private.
+ return std::unique_ptr<Instruction>(new Instruction(
+ Description, InstrInfo.getName(Opcode), std::move(Operands),
+ std::move(Variables), BVC.getUnique(std::move(ImplDefRegs)),
+ BVC.getUnique(std::move(ImplUseRegs)),
+ BVC.getUnique(std::move(AllDefRegs)),
+ BVC.getUnique(std::move(AllUseRegs))));
+}
+
+const Operand &Instruction::getPrimaryOperand(const Variable &Var) const {
+ const auto PrimaryOperandIndex = Var.getPrimaryOperandIndex();
+ assert(PrimaryOperandIndex < Operands.size());
+ return Operands[PrimaryOperandIndex];
+}
+
+bool Instruction::hasMemoryOperands() const {
+ return any_of(Operands, [](const Operand &Op) {
+ return Op.isReg() && Op.isExplicit() && Op.isMemory();
+ });
+}
+
+bool Instruction::hasAliasingImplicitRegisters() const {
+ return ImplDefRegs.anyCommon(ImplUseRegs);
+}
+
+// Returns true if there are registers that are both in `A` and `B` but not in
+// `Forbidden`.
+static bool anyCommonExcludingForbidden(const BitVector &A, const BitVector &B,
+ const BitVector &Forbidden) {
+ assert(A.size() == B.size() && B.size() == Forbidden.size());
+ const auto Size = A.size();
+ for (int AIndex = A.find_first(); AIndex != -1;) {
+ const int BIndex = B.find_first_in(AIndex, Size);
+ if (BIndex == -1)
+ return false;
+ if (AIndex == BIndex && !Forbidden.test(AIndex))
+ return true;
+ AIndex = A.find_first_in(BIndex + 1, Size);
+ }
+ return false;
+}
+
+bool Instruction::hasAliasingRegistersThrough(
+ const Instruction &OtherInstr, const BitVector &ForbiddenRegisters) const {
+ return anyCommonExcludingForbidden(AllDefRegs, OtherInstr.AllUseRegs,
+ ForbiddenRegisters) &&
+ anyCommonExcludingForbidden(OtherInstr.AllDefRegs, AllUseRegs,
+ ForbiddenRegisters);
+}
+
+bool Instruction::hasTiedRegisters() const {
+ return any_of(Variables,
+ [](const Variable &Var) { return Var.hasTiedOperands(); });
+}
+
+bool Instruction::hasAliasingRegisters(
+ const BitVector &ForbiddenRegisters) const {
+ return anyCommonExcludingForbidden(AllDefRegs, AllUseRegs,
+ ForbiddenRegisters);
+}
+
+bool Instruction::hasOneUseOrOneDef() const {
+ return AllDefRegs.count() || AllUseRegs.count();
+}
+
+void Instruction::dump(const MCRegisterInfo &RegInfo,
+ const RegisterAliasingTrackerCache &RATC,
+ raw_ostream &Stream) const {
+ Stream << "- " << Name << "\n";
+ for (const auto &Op : Operands) {
+ Stream << "- Op" << Op.getIndex();
+ if (Op.isExplicit())
+ Stream << " Explicit";
+ if (Op.isImplicit())
+ Stream << " Implicit";
+ if (Op.isUse())
+ Stream << " Use";
+ if (Op.isDef())
+ Stream << " Def";
+ if (Op.isImmediate())
+ Stream << " Immediate";
+ if (Op.isMemory())
+ Stream << " Memory";
+ if (Op.isReg()) {
+ if (Op.isImplicitReg())
+ Stream << " Reg(" << RegInfo.getName(Op.getImplicitReg()) << ")";
+ else
+ Stream << " RegClass("
+ << RegInfo.getRegClassName(
+ &RegInfo.getRegClass(Op.Info->RegClass))
+ << ")";
+ }
+ if (Op.isTied())
+ Stream << " TiedToOp" << Op.getTiedToIndex();
+ Stream << "\n";
+ }
+ for (const auto &Var : Variables) {
+ Stream << "- Var" << Var.getIndex();
+ Stream << " [";
+ bool IsFirst = true;
+ for (auto OperandIndex : Var.TiedOperands) {
+ if (!IsFirst)
+ Stream << ",";
+ Stream << "Op" << OperandIndex;
+ IsFirst = false;
+ }
+ Stream << "]";
+ Stream << "\n";
+ }
+ if (hasMemoryOperands())
+ Stream << "- hasMemoryOperands\n";
+ if (hasAliasingImplicitRegisters())
+ Stream << "- hasAliasingImplicitRegisters (execution is always serial)\n";
+ if (hasTiedRegisters())
+ Stream << "- hasTiedRegisters (execution is always serial)\n";
+ if (hasAliasingRegisters(RATC.emptyRegisters()))
+ Stream << "- hasAliasingRegisters\n";
+}
+
+InstructionsCache::InstructionsCache(const MCInstrInfo &InstrInfo,
+ const RegisterAliasingTrackerCache &RATC)
+ : InstrInfo(InstrInfo), RATC(RATC), BVC() {}
+
+const Instruction &InstructionsCache::getInstr(unsigned Opcode) const {
+ auto &Found = Instructions[Opcode];
+ if (!Found)
+ Found = Instruction::create(InstrInfo, RATC, BVC, Opcode);
+ return *Found;
+}
+
+bool RegisterOperandAssignment::
+operator==(const RegisterOperandAssignment &Other) const {
+ return std::tie(Op, Reg) == std::tie(Other.Op, Other.Reg);
+}
+
+bool AliasingRegisterOperands::
+operator==(const AliasingRegisterOperands &Other) const {
+ return std::tie(Defs, Uses) == std::tie(Other.Defs, Other.Uses);
+}
+
+static void
+addOperandIfAlias(const MCPhysReg Reg, bool SelectDef,
+ ArrayRef<Operand> Operands,
+ SmallVectorImpl<RegisterOperandAssignment> &OperandValues) {
+ for (const auto &Op : Operands) {
+ if (Op.isReg() && Op.isDef() == SelectDef) {
+ const int SourceReg = Op.getRegisterAliasing().getOrigin(Reg);
+ if (SourceReg >= 0)
+ OperandValues.emplace_back(&Op, SourceReg);
+ }
+ }
+}
+
+bool AliasingRegisterOperands::hasImplicitAliasing() const {
+ const auto HasImplicit = [](const RegisterOperandAssignment &ROV) {
+ return ROV.Op->isImplicit();
+ };
+ return any_of(Defs, HasImplicit) && any_of(Uses, HasImplicit);
+}
+
+bool AliasingConfigurations::empty() const { return Configurations.empty(); }
+
+bool AliasingConfigurations::hasImplicitAliasing() const {
+ return any_of(Configurations, [](const AliasingRegisterOperands &ARO) {
+ return ARO.hasImplicitAliasing();
+ });
+}
+
+AliasingConfigurations::AliasingConfigurations(
+ const Instruction &DefInstruction, const Instruction &UseInstruction) {
+ if (UseInstruction.AllUseRegs.anyCommon(DefInstruction.AllDefRegs)) {
+ auto CommonRegisters = UseInstruction.AllUseRegs;
+ CommonRegisters &= DefInstruction.AllDefRegs;
+ for (const MCPhysReg Reg : CommonRegisters.set_bits()) {
+ AliasingRegisterOperands ARO;
+ addOperandIfAlias(Reg, true, DefInstruction.Operands, ARO.Defs);
+ addOperandIfAlias(Reg, false, UseInstruction.Operands, ARO.Uses);
+ if (!ARO.Defs.empty() && !ARO.Uses.empty() &&
+ !is_contained(Configurations, ARO))
+ Configurations.push_back(std::move(ARO));
+ }
+ }
+}
+
+void DumpMCOperand(const MCRegisterInfo &MCRegisterInfo, const MCOperand &Op,
+ raw_ostream &OS) {
+ if (!Op.isValid())
+ OS << "Invalid";
+ else if (Op.isReg())
+ OS << MCRegisterInfo.getName(Op.getReg());
+ else if (Op.isImm())
+ OS << Op.getImm();
+ else if (Op.isFPImm())
+ OS << Op.getFPImm();
+ else if (Op.isExpr())
+ OS << "Expr";
+ else if (Op.isInst())
+ OS << "SubInst";
+}
+
+void DumpMCInst(const MCRegisterInfo &MCRegisterInfo,
+ const MCInstrInfo &MCInstrInfo, const MCInst &MCInst,
+ raw_ostream &OS) {
+ OS << MCInstrInfo.getName(MCInst.getOpcode());
+ for (unsigned I = 0, E = MCInst.getNumOperands(); I < E; ++I) {
+ if (I > 0)
+ OS << ',';
+ OS << ' ';
+ DumpMCOperand(MCRegisterInfo, MCInst.getOperand(I), OS);
+ }
+}
+
+} // namespace exegesis
+} // namespace llvm