Skip to content

Commit

Permalink
[llvm-exegesis] Factor out DisassemblerHelper from the Analysis class
Browse files Browse the repository at this point in the history
As part of preparing the reports, the Analysis class needs to print
machine instructions in a disassembled form. For this purpose, the class
has four fields (namely Context_, AsmInfo_, InstPrinter_ and Disasm_).
All the constructor of the Analysis class does is conditionally
initializing these four fields.

This commit factors out the logic for decoding machine code and printing
it in an assembler form into a separate DisassemblerHelper class.

~~

Huawei RRI, OS Lab

Reviewed By: courbet

Differential Revision: https://reviews.llvm.org/D147156
  • Loading branch information
kpdev committed Apr 4, 2023
1 parent 1f60c8d commit 39fc67b
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 26 deletions.
21 changes: 3 additions & 18 deletions llvm/tools/llvm-exegesis/lib/Analysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,20 +102,19 @@ template <typename EscapeTag, EscapeTag Tag>
void Analysis::writeSnippet(raw_ostream &OS, ArrayRef<uint8_t> Bytes,
const char *Separator) const {
SmallVector<std::string, 3> Lines;
const auto &SI = State_.getSubtargetInfo();
// Parse the asm snippet and print it.
while (!Bytes.empty()) {
MCInst MI;
uint64_t MISize = 0;
if (!Disasm_->getInstruction(MI, MISize, Bytes, 0, nulls())) {
if (!DisasmHelper_->decodeInst(MI, MISize, Bytes)) {
writeEscaped<Tag>(OS, join(Lines, Separator));
writeEscaped<Tag>(OS, Separator);
writeEscaped<Tag>(OS, "[error decoding asm snippet]");
return;
}
SmallString<128> InstPrinterStr; // FIXME: magic number.
raw_svector_ostream OSS(InstPrinterStr);
InstPrinter_->printInst(&MI, 0, "", SI, OSS);
DisasmHelper_->printInst(&MI, OSS);
Bytes = Bytes.drop_front(MISize);
Lines.emplace_back(InstPrinterStr.str().trim());
}
Expand Down Expand Up @@ -163,21 +162,7 @@ Analysis::Analysis(const LLVMState &State,
if (Clustering.getPoints().empty())
return;

MCTargetOptions MCOptions;
const auto &TM = State.getTargetMachine();
const auto &Triple = TM.getTargetTriple();
AsmInfo_.reset(TM.getTarget().createMCAsmInfo(State_.getRegInfo(),
Triple.str(), MCOptions));
InstPrinter_.reset(TM.getTarget().createMCInstPrinter(
Triple, 0 /*default variant*/, *AsmInfo_, State_.getInstrInfo(),
State_.getRegInfo()));

Context_ = std::make_unique<MCContext>(
Triple, AsmInfo_.get(), &State_.getRegInfo(), &State_.getSubtargetInfo());
Disasm_.reset(TM.getTarget().createMCDisassembler(State_.getSubtargetInfo(),
*Context_));
assert(Disasm_ && "cannot create MCDisassembler. missing call to "
"InitializeXXXTargetDisassembler ?");
DisasmHelper_ = std::make_unique<DisassemblerHelper>(State);
}

template <>
Expand Down
10 changes: 2 additions & 8 deletions llvm/tools/llvm-exegesis/lib/Analysis.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,11 @@
#define LLVM_TOOLS_LLVM_EXEGESIS_ANALYSIS_H

#include "Clustering.h"
#include "DisassemblerHelper.h"
#include "SchedClassResolution.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCDisassembler/MCDisassembler.h"
#include "llvm/MC/MCInstPrinter.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/raw_ostream.h"
#include <memory>
Expand Down Expand Up @@ -112,10 +109,7 @@ class Analysis {

const BenchmarkClustering &Clustering_;
const LLVMState &State_;
std::unique_ptr<MCContext> Context_;
std::unique_ptr<MCAsmInfo> AsmInfo_;
std::unique_ptr<MCInstPrinter> InstPrinter_;
std::unique_ptr<MCDisassembler> Disasm_;
std::unique_ptr<DisassemblerHelper> DisasmHelper_;
const double AnalysisInconsistencyEpsilonSquared_;
const bool AnalysisDisplayUnstableOpcodes_;
};
Expand Down
1 change: 1 addition & 0 deletions llvm/tools/llvm-exegesis/lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ add_llvm_library(LLVMExegesis
BenchmarkRunner.cpp
Clustering.cpp
CodeTemplate.cpp
DisassemblerHelper.cpp
Error.cpp
LatencyBenchmarkRunner.cpp
LlvmState.cpp
Expand Down
35 changes: 35 additions & 0 deletions llvm/tools/llvm-exegesis/lib/DisassemblerHelper.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//===-- DisassemblerHelper.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 "DisassemblerHelper.h"

#include "llvm/MC/TargetRegistry.h"

namespace llvm {
namespace exegesis {

DisassemblerHelper::DisassemblerHelper(const LLVMState &State) : State_(State) {
MCTargetOptions MCOptions;
const auto &TM = State.getTargetMachine();
const auto &Triple = TM.getTargetTriple();
AsmInfo_.reset(TM.getTarget().createMCAsmInfo(State_.getRegInfo(),
Triple.str(), MCOptions));
InstPrinter_.reset(TM.getTarget().createMCInstPrinter(
Triple, 0 /*default variant*/, *AsmInfo_, State_.getInstrInfo(),
State_.getRegInfo()));

Context_ = std::make_unique<MCContext>(
Triple, AsmInfo_.get(), &State_.getRegInfo(), &State_.getSubtargetInfo());
Disasm_.reset(TM.getTarget().createMCDisassembler(State_.getSubtargetInfo(),
*Context_));
assert(Disasm_ && "cannot create MCDisassembler. missing call to "
"InitializeXXXTargetDisassembler ?");
}

} // namespace exegesis
} // namespace llvm
54 changes: 54 additions & 0 deletions llvm/tools/llvm-exegesis/lib/DisassemblerHelper.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
//===-- DisassemblerHelper.h ------------------------------------*- 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
//
//===----------------------------------------------------------------------===//
///
/// \file
/// Helper class for decoding machine instructions and printing them in an
/// assembler form.
///
//===----------------------------------------------------------------------===//

#ifndef LLVM_TOOLS_LLVM_EXEGESIS_DISASSEMBLER_HELPER_H
#define LLVM_TOOLS_LLVM_EXEGESIS_DISASSEMBLER_HELPER_H

#include "LlvmState.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCDisassembler/MCDisassembler.h"
#include "llvm/MC/MCInstPrinter.h"

#include <memory>

namespace llvm {
namespace exegesis {

// A helper class for decoding and printing machine instructions.
class DisassemblerHelper {
public:
DisassemblerHelper(const LLVMState &State);

void printInst(const MCInst *MI, raw_ostream &OS) const {
const auto &STI = State_.getSubtargetInfo();
InstPrinter_->printInst(MI, 0, "", STI, OS);
}

bool decodeInst(MCInst &MI, uint64_t &MISize, ArrayRef<uint8_t> Bytes) const {
return Disasm_->getInstruction(MI, MISize, Bytes, 0, nulls());
}

private:
const LLVMState &State_;
std::unique_ptr<MCContext> Context_;
std::unique_ptr<MCAsmInfo> AsmInfo_;
std::unique_ptr<MCInstPrinter> InstPrinter_;
std::unique_ptr<MCDisassembler> Disasm_;
};

} // namespace exegesis
} // namespace llvm

#endif // LLVM_TOOLS_LLVM_EXEGESIS_DISASSEMBLER_HELPER_H

0 comments on commit 39fc67b

Please sign in to comment.