diff options
author | vitalyisaev <vitalyisaev@yandex-team.com> | 2023-06-29 10:00:50 +0300 |
---|---|---|
committer | vitalyisaev <vitalyisaev@yandex-team.com> | 2023-06-29 10:00:50 +0300 |
commit | 6ffe9e53658409f212834330e13564e4952558f6 (patch) | |
tree | 85b1e00183517648b228aafa7c8fb07f5276f419 /contrib/libs/llvm14/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp | |
parent | 726057070f9c5a91fc10fde0d5024913d10f1ab9 (diff) | |
download | ydb-6ffe9e53658409f212834330e13564e4952558f6.tar.gz |
YQ Connector: support managed ClickHouse
Со стороны dqrun можно обратиться к инстансу коннектора, который работает на streaming стенде, и извлечь данные из облачного CH.
Diffstat (limited to 'contrib/libs/llvm14/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp')
-rw-r--r-- | contrib/libs/llvm14/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/contrib/libs/llvm14/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp b/contrib/libs/llvm14/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp new file mode 100644 index 0000000000..962136a1f8 --- /dev/null +++ b/contrib/libs/llvm14/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp @@ -0,0 +1,181 @@ +//===-- SerialSnippetGenerator.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 "SerialSnippetGenerator.h" + +#include "CodeTemplate.h" +#include "MCInstrDescView.h" +#include "Target.h" +#include <algorithm> +#include <numeric> +#include <vector> + +namespace llvm { +namespace exegesis { + +struct ExecutionClass { + ExecutionMode Mask; + const char *Description; +} static const kExecutionClasses[] = { + {ExecutionMode::ALWAYS_SERIAL_IMPLICIT_REGS_ALIAS | + ExecutionMode::ALWAYS_SERIAL_TIED_REGS_ALIAS, + "Repeating a single implicitly serial instruction"}, + {ExecutionMode::SERIAL_VIA_EXPLICIT_REGS, + "Repeating a single explicitly serial instruction"}, + {ExecutionMode::SERIAL_VIA_MEMORY_INSTR | + ExecutionMode::SERIAL_VIA_NON_MEMORY_INSTR, + "Repeating two instructions"}, +}; + +static constexpr size_t kMaxAliasingInstructions = 10; + +static std::vector<const Instruction *> +computeAliasingInstructions(const LLVMState &State, const Instruction *Instr, + size_t MaxAliasingInstructions, + const BitVector &ForbiddenRegisters) { + // Randomly iterate the set of instructions. + std::vector<unsigned> Opcodes; + Opcodes.resize(State.getInstrInfo().getNumOpcodes()); + std::iota(Opcodes.begin(), Opcodes.end(), 0U); + llvm::shuffle(Opcodes.begin(), Opcodes.end(), randomGenerator()); + + std::vector<const Instruction *> AliasingInstructions; + for (const unsigned OtherOpcode : Opcodes) { + if (OtherOpcode == Instr->Description.getOpcode()) + continue; + const Instruction &OtherInstr = State.getIC().getInstr(OtherOpcode); + const MCInstrDesc &OtherInstrDesc = OtherInstr.Description; + // Ignore instructions that we cannot run. + if (OtherInstrDesc.isPseudo() || OtherInstrDesc.usesCustomInsertionHook() || + OtherInstrDesc.isBranch() || OtherInstrDesc.isIndirectBranch() || + OtherInstrDesc.isCall() || OtherInstrDesc.isReturn()) { + continue; + } + if (OtherInstr.hasMemoryOperands()) + continue; + if (!State.getExegesisTarget().allowAsBackToBack(OtherInstr)) + continue; + if (Instr->hasAliasingRegistersThrough(OtherInstr, ForbiddenRegisters)) + AliasingInstructions.push_back(&OtherInstr); + if (AliasingInstructions.size() >= MaxAliasingInstructions) + break; + } + return AliasingInstructions; +} + +static ExecutionMode getExecutionModes(const Instruction &Instr, + const BitVector &ForbiddenRegisters) { + ExecutionMode EM = ExecutionMode::UNKNOWN; + if (Instr.hasAliasingImplicitRegisters()) + EM |= ExecutionMode::ALWAYS_SERIAL_IMPLICIT_REGS_ALIAS; + if (Instr.hasTiedRegisters()) + EM |= ExecutionMode::ALWAYS_SERIAL_TIED_REGS_ALIAS; + if (Instr.hasMemoryOperands()) + EM |= ExecutionMode::SERIAL_VIA_MEMORY_INSTR; + else { + if (Instr.hasAliasingRegisters(ForbiddenRegisters)) + EM |= ExecutionMode::SERIAL_VIA_EXPLICIT_REGS; + if (Instr.hasOneUseOrOneDef()) + EM |= ExecutionMode::SERIAL_VIA_NON_MEMORY_INSTR; + } + return EM; +} + +static void appendCodeTemplates(const LLVMState &State, + InstructionTemplate Variant, + const BitVector &ForbiddenRegisters, + ExecutionMode ExecutionModeBit, + StringRef ExecutionClassDescription, + std::vector<CodeTemplate> &CodeTemplates) { + assert(isEnumValue(ExecutionModeBit) && "Bit must be a power of two"); + switch (ExecutionModeBit) { + case ExecutionMode::ALWAYS_SERIAL_IMPLICIT_REGS_ALIAS: + // Nothing to do, the instruction is always serial. + LLVM_FALLTHROUGH; + case ExecutionMode::ALWAYS_SERIAL_TIED_REGS_ALIAS: { + // Picking whatever value for the tied variable will make the instruction + // serial. + CodeTemplate CT; + CT.Execution = ExecutionModeBit; + CT.Info = std::string(ExecutionClassDescription); + CT.Instructions.push_back(std::move(Variant)); + CodeTemplates.push_back(std::move(CT)); + return; + } + case ExecutionMode::SERIAL_VIA_MEMORY_INSTR: { + // Select back-to-back memory instruction. + // TODO: Implement me. + return; + } + case ExecutionMode::SERIAL_VIA_EXPLICIT_REGS: { + // Making the execution of this instruction serial by selecting one def + // register to alias with one use register. + const AliasingConfigurations SelfAliasing(Variant.getInstr(), + Variant.getInstr()); + assert(!SelfAliasing.empty() && !SelfAliasing.hasImplicitAliasing() && + "Instr must alias itself explicitly"); + // This is a self aliasing instruction so defs and uses are from the same + // instance, hence twice Variant in the following call. + setRandomAliasing(SelfAliasing, Variant, Variant); + CodeTemplate CT; + CT.Execution = ExecutionModeBit; + CT.Info = std::string(ExecutionClassDescription); + CT.Instructions.push_back(std::move(Variant)); + CodeTemplates.push_back(std::move(CT)); + return; + } + case ExecutionMode::SERIAL_VIA_NON_MEMORY_INSTR: { + const Instruction &Instr = Variant.getInstr(); + // Select back-to-back non-memory instruction. + for (const auto *OtherInstr : computeAliasingInstructions( + State, &Instr, kMaxAliasingInstructions, ForbiddenRegisters)) { + const AliasingConfigurations Forward(Instr, *OtherInstr); + const AliasingConfigurations Back(*OtherInstr, Instr); + InstructionTemplate ThisIT(Variant); + InstructionTemplate OtherIT(OtherInstr); + if (!Forward.hasImplicitAliasing()) + setRandomAliasing(Forward, ThisIT, OtherIT); + else if (!Back.hasImplicitAliasing()) + setRandomAliasing(Back, OtherIT, ThisIT); + CodeTemplate CT; + CT.Execution = ExecutionModeBit; + CT.Info = std::string(ExecutionClassDescription); + CT.Instructions.push_back(std::move(ThisIT)); + CT.Instructions.push_back(std::move(OtherIT)); + CodeTemplates.push_back(std::move(CT)); + } + return; + } + default: + llvm_unreachable("Unhandled enum value"); + } +} + +SerialSnippetGenerator::~SerialSnippetGenerator() = default; + +Expected<std::vector<CodeTemplate>> +SerialSnippetGenerator::generateCodeTemplates( + InstructionTemplate Variant, const BitVector &ForbiddenRegisters) const { + std::vector<CodeTemplate> Results; + const ExecutionMode EM = + getExecutionModes(Variant.getInstr(), ForbiddenRegisters); + for (const auto EC : kExecutionClasses) { + for (const auto ExecutionModeBit : getExecutionModeBits(EM & EC.Mask)) + appendCodeTemplates(State, Variant, ForbiddenRegisters, ExecutionModeBit, + EC.Description, Results); + if (!Results.empty()) + break; + } + if (Results.empty()) + return make_error<Failure>( + "No strategy found to make the execution serial"); + return std::move(Results); +} + +} // namespace exegesis +} // namespace llvm |