}
llvm::Expected<CodeTemplate>
-LatencySnippetGenerator::generateCodeTemplate(unsigned Opcode) const {
- const Instruction Instr(State, Opcode);
+LatencySnippetGenerator::generateCodeTemplate(const Instruction &Instr) const {
if (Instr.hasMemoryOperands())
return llvm::make_error<BenchmarkFailure>(
"Infeasible : has memory operands");
~LatencySnippetGenerator() override;
llvm::Expected<CodeTemplate>
- generateCodeTemplate(unsigned Opcode) const override;
+ generateCodeTemplate(const Instruction &Instr) const override;
private:
llvm::Expected<CodeTemplate>
}
Instruction::Instruction(const LLVMState &State, unsigned Opcode)
- : Description(&State.getInstrInfo().get(Opcode)) {
+ : Description(&State.getInstrInfo().get(Opcode)),
+ Name(State.getInstrInfo().getName(Opcode)) {
const auto &RATC = State.getRATC();
unsigned OpIndex = 0;
for (; OpIndex < Description->getNumOperands(); ++OpIndex) {
void Instruction::dump(const llvm::MCRegisterInfo &RegInfo,
llvm::raw_ostream &Stream) const {
+ Stream << "- " << Name << "\n";
for (const auto &Op : Operands) {
Stream << "- Op" << Op.getIndex();
if (Op.isExplicit())
}
for (const auto &Var : Variables) {
Stream << "- Var" << Var.getIndex();
- Stream << " (";
- for (auto OperandIndex : Var.TiedOperands)
+ Stream << " [";
+ bool IsFirst = true;
+ for (auto OperandIndex : Var.TiedOperands) {
+ if (!IsFirst)
+ Stream << ",";
Stream << "Op" << OperandIndex;
- Stream << ")";
+ IsFirst = false;
+ }
+ Stream << "]";
Stream << "\n";
}
if (hasMemoryOperands())
llvm::raw_ostream &Stream) const;
const llvm::MCInstrDesc *Description; // Never nullptr.
+ llvm::StringRef Name; // The name of this instruction.
llvm::SmallVector<Operand, 8> Operands;
llvm::SmallVector<Variable, 4> Variables;
llvm::BitVector ImplDefRegs; // The set of aliased implicit def registers.
SnippetGenerator::~SnippetGenerator() = default;
llvm::Expected<std::vector<BenchmarkCode>>
-SnippetGenerator::generateConfigurations(unsigned Opcode) const {
- if (auto E = generateCodeTemplate(Opcode)) {
+SnippetGenerator::generateConfigurations(const Instruction &Instr) const {
+ if (auto E = generateCodeTemplate(Instr)) {
CodeTemplate &CT = E.get();
const auto &RATC = State.getRATC();
const llvm::BitVector &ForbiddenRegs =
// Calls generateCodeTemplate and expands it into one or more BenchmarkCode.
llvm::Expected<std::vector<BenchmarkCode>>
- generateConfigurations(unsigned Opcode) const;
+ generateConfigurations(const Instruction &Instr) const;
// Given a snippet, computes which registers the setup code needs to define.
std::vector<RegisterValue> computeRegisterInitialValues(
private:
// API to be implemented by subclasses.
virtual llvm::Expected<CodeTemplate>
- generateCodeTemplate(unsigned Opcode) const = 0;
+ generateCodeTemplate(const Instruction &Instr) const = 0;
};
// A global Random Number Generator to randomize configurations.
}
llvm::Expected<CodeTemplate>
-UopsSnippetGenerator::generateCodeTemplate(unsigned Opcode) const {
- const auto &ET = State.getExegesisTarget();
+UopsSnippetGenerator::generateCodeTemplate(const Instruction &Instr) const {
CodeTemplate CT;
-
const llvm::BitVector *ScratchSpaceAliasedRegs = nullptr;
- const Instruction Instr(State, Opcode);
if (Instr.hasMemoryOperands()) {
+ const auto &ET = State.getExegesisTarget();
CT.ScratchSpacePointerInReg =
ET.getScratchMemoryRegister(State.getTargetMachine().getTargetTriple());
if (CT.ScratchSpacePointerInReg == 0)
~UopsSnippetGenerator() override;
llvm::Expected<CodeTemplate>
- generateCodeTemplate(unsigned Opcode) const override;
+ generateCodeTemplate(const Instruction &Instr) const override;
static constexpr const size_t kMinNumDifferentAddresses = 6;
using Impl::Impl;
llvm::Expected<CodeTemplate>
- generateCodeTemplate(unsigned Opcode) const override {
+ generateCodeTemplate(const Instruction &Instr) const override {
// Test whether we can generate a snippet for this instruction.
- const auto &InstrInfo = this->State.getInstrInfo();
- const auto OpcodeName = InstrInfo.getName(Opcode);
+ const auto OpcodeName = Instr.Name;
if (OpcodeName.startswith("POPF") || OpcodeName.startswith("PUSHF") ||
OpcodeName.startswith("ADJCALLSTACK")) {
return llvm::make_error<BenchmarkFailure>(
// Handle X87.
const unsigned FPInstClass =
- InstrInfo.get(Opcode).TSFlags & llvm::X86II::FPTypeMask;
- const Instruction Instr(this->State, Opcode);
+ Instr.Description->TSFlags & llvm::X86II::FPTypeMask;
switch (FPInstClass) {
case llvm::X86II::NotFP:
break;
}
// Fallback to generic implementation.
- return Impl::Base::generateCodeTemplate(Opcode);
+ return Impl::Base::generateCodeTemplate(Instr);
}
};
// Generates code snippets for opcode `Opcode`.
static llvm::Expected<std::vector<BenchmarkCode>>
generateSnippets(const LLVMState &State, unsigned Opcode) {
- const std::unique_ptr<SnippetGenerator> Generator =
- State.getExegesisTarget().createSnippetGenerator(BenchmarkMode, State);
- if (!Generator)
- llvm::report_fatal_error("cannot create snippet generator");
-
- const llvm::MCInstrDesc &InstrDesc = State.getInstrInfo().get(Opcode);
+ const Instruction Instr(State, Opcode);
+ const llvm::MCInstrDesc &InstrDesc = *Instr.Description;
// Ignore instructions that we cannot run.
if (InstrDesc.isPseudo())
return llvm::make_error<BenchmarkFailure>("Unsupported opcode: isPseudo");
return llvm::make_error<BenchmarkFailure>(
"Unsupported opcode: isCall/isReturn");
- return Generator->generateConfigurations(Opcode);
+ const std::unique_ptr<SnippetGenerator> Generator =
+ State.getExegesisTarget().createSnippetGenerator(BenchmarkMode, State);
+ if (!Generator)
+ llvm::report_fatal_error("cannot create snippet generator");
+ return Generator->generateConfigurations(Instr);
}
namespace {
CodeTemplate checkAndGetCodeTemplate(unsigned Opcode) {
randomGenerator().seed(0); // Initialize seed.
- auto CodeTemplateOrError = Generator.generateCodeTemplate(Opcode);
+ const Instruction Instr(State, Opcode);
+ auto CodeTemplateOrError = Generator.generateCodeTemplate(Instr);
EXPECT_FALSE(CodeTemplateOrError.takeError()); // Valid configuration.
return std::move(CodeTemplateOrError.get());
}
TEST_F(UopsSnippetGeneratorTest, MemoryUse_Movsb) {
// MOVSB writes to scratch memory register.
const unsigned Opcode = llvm::X86::MOVSB;
- auto Error = Generator.generateCodeTemplate(Opcode).takeError();
+ const Instruction Instr(State, Opcode);
+ auto Error = Generator.generateCodeTemplate(Instr).takeError();
EXPECT_TRUE((bool)Error);
llvm::consumeError(std::move(Error));
}
private:
llvm::Expected<CodeTemplate>
- generateCodeTemplate(unsigned Opcode) const override {
+ generateCodeTemplate(const Instruction &Instr) const override {
return llvm::make_error<llvm::StringError>("not implemented",
llvm::inconvertibleErrorCode());
}