aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/llvm14/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp
diff options
context:
space:
mode:
authorvitalyisaev <vitalyisaev@yandex-team.com>2023-06-29 10:00:50 +0300
committervitalyisaev <vitalyisaev@yandex-team.com>2023-06-29 10:00:50 +0300
commit6ffe9e53658409f212834330e13564e4952558f6 (patch)
tree85b1e00183517648b228aafa7c8fb07f5276f419 /contrib/libs/llvm14/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp
parent726057070f9c5a91fc10fde0d5024913d10f1ab9 (diff)
downloadydb-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.cpp181
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