Mercurial > hg > CbC > CbC_llvm
diff tools/llvm-exegesis/lib/Target.cpp @ 147:c2174574ed3a
LLVM 10
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Wed, 14 Aug 2019 16:55:33 +0900 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/llvm-exegesis/lib/Target.cpp Wed Aug 14 16:55:33 2019 +0900 @@ -0,0 +1,172 @@ +//===-- Target.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 "Target.h" + +#include "Latency.h" +#include "Uops.h" + +namespace llvm { +namespace exegesis { + +ExegesisTarget::~ExegesisTarget() {} // anchor. + +static ExegesisTarget *FirstTarget = nullptr; + +const ExegesisTarget *ExegesisTarget::lookup(llvm::Triple TT) { + for (const ExegesisTarget *T = FirstTarget; T != nullptr; T = T->Next) { + if (T->matchesArch(TT.getArch())) + return T; + } + return nullptr; +} + +void ExegesisTarget::registerTarget(ExegesisTarget *Target) { + if (FirstTarget == nullptr) { + FirstTarget = Target; + return; + } + if (Target->Next != nullptr) + return; // Already registered. + Target->Next = FirstTarget; + FirstTarget = Target; +} + +std::unique_ptr<SnippetGenerator> +ExegesisTarget::createSnippetGenerator(InstructionBenchmark::ModeE Mode, + const LLVMState &State) const { + switch (Mode) { + case InstructionBenchmark::Unknown: + return nullptr; + case InstructionBenchmark::Latency: + return createLatencySnippetGenerator(State); + case InstructionBenchmark::Uops: + case InstructionBenchmark::InverseThroughput: + return createUopsSnippetGenerator(State); + } + return nullptr; +} + +std::unique_ptr<BenchmarkRunner> +ExegesisTarget::createBenchmarkRunner(InstructionBenchmark::ModeE Mode, + const LLVMState &State) const { + switch (Mode) { + case InstructionBenchmark::Unknown: + return nullptr; + case InstructionBenchmark::Latency: + case InstructionBenchmark::InverseThroughput: + return createLatencyBenchmarkRunner(State, Mode); + case InstructionBenchmark::Uops: + return createUopsBenchmarkRunner(State); + } + return nullptr; +} + +std::unique_ptr<SnippetGenerator> +ExegesisTarget::createLatencySnippetGenerator(const LLVMState &State) const { + return llvm::make_unique<LatencySnippetGenerator>(State); +} + +std::unique_ptr<SnippetGenerator> +ExegesisTarget::createUopsSnippetGenerator(const LLVMState &State) const { + return llvm::make_unique<UopsSnippetGenerator>(State); +} + +std::unique_ptr<BenchmarkRunner> ExegesisTarget::createLatencyBenchmarkRunner( + const LLVMState &State, InstructionBenchmark::ModeE Mode) const { + return llvm::make_unique<LatencyBenchmarkRunner>(State, Mode); +} + +std::unique_ptr<BenchmarkRunner> +ExegesisTarget::createUopsBenchmarkRunner(const LLVMState &State) const { + return llvm::make_unique<UopsBenchmarkRunner>(State); +} + +void ExegesisTarget::randomizeMCOperand( + const Instruction &Instr, const Variable &Var, + llvm::MCOperand &AssignedValue, + const llvm::BitVector &ForbiddenRegs) const { + const Operand &Op = Instr.getPrimaryOperand(Var); + switch (Op.getExplicitOperandInfo().OperandType) { + case llvm::MCOI::OperandType::OPERAND_IMMEDIATE: + // FIXME: explore immediate values too. + AssignedValue = llvm::MCOperand::createImm(1); + break; + case llvm::MCOI::OperandType::OPERAND_REGISTER: { + assert(Op.isReg()); + auto AllowedRegs = Op.getRegisterAliasing().sourceBits(); + assert(AllowedRegs.size() == ForbiddenRegs.size()); + for (auto I : ForbiddenRegs.set_bits()) + AllowedRegs.reset(I); + AssignedValue = llvm::MCOperand::createReg(randomBit(AllowedRegs)); + break; + } + default: + break; + } +} + +static_assert(std::is_pod<PfmCountersInfo>::value, + "We shouldn't have dynamic initialization here"); +const PfmCountersInfo PfmCountersInfo::Default = {nullptr, nullptr, nullptr, + 0u}; + +const PfmCountersInfo & +ExegesisTarget::getPfmCounters(llvm::StringRef CpuName) const { + assert(std::is_sorted( + CpuPfmCounters.begin(), CpuPfmCounters.end(), + [](const CpuAndPfmCounters &LHS, const CpuAndPfmCounters &RHS) { + return strcmp(LHS.CpuName, RHS.CpuName) < 0; + }) && + "CpuPfmCounters table is not sorted"); + + // Find entry + auto Found = + std::lower_bound(CpuPfmCounters.begin(), CpuPfmCounters.end(), CpuName); + if (Found == CpuPfmCounters.end() || + llvm::StringRef(Found->CpuName) != CpuName) { + // Use the default. + if (CpuPfmCounters.begin() != CpuPfmCounters.end() && + CpuPfmCounters.begin()->CpuName[0] == '\0') { + Found = CpuPfmCounters.begin(); // The target specifies a default. + } else { + return PfmCountersInfo::Default; // No default for the target. + } + } + assert(Found->PCI && "Missing counters"); + return *Found->PCI; +} + +namespace { + +// Default implementation. +class ExegesisDefaultTarget : public ExegesisTarget { +public: + ExegesisDefaultTarget() : ExegesisTarget({}) {} + +private: + std::vector<llvm::MCInst> setRegTo(const llvm::MCSubtargetInfo &STI, + unsigned Reg, + const llvm::APInt &Value) const override { + llvm_unreachable("Not yet implemented"); + } + + bool matchesArch(llvm::Triple::ArchType Arch) const override { + llvm_unreachable("never called"); + return false; + } +}; + +} // namespace + +const ExegesisTarget &ExegesisTarget::getDefault() { + static ExegesisDefaultTarget Target; + return Target; +} + +} // namespace exegesis +} // namespace llvm