diff options
author | monster <monster@ydb.tech> | 2022-07-07 14:41:37 +0300 |
---|---|---|
committer | monster <monster@ydb.tech> | 2022-07-07 14:41:37 +0300 |
commit | 06e5c21a835c0e923506c4ff27929f34e00761c2 (patch) | |
tree | 75efcbc6854ef9bd476eb8bf00cc5c900da436a2 /contrib/libs/llvm12/tools/llvm-exegesis/lib/MCInstrDescView.cpp | |
parent | 03f024c4412e3aa613bb543cf1660176320ba8f4 (diff) | |
download | ydb-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.cpp | 398 |
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 |