[llvm-mca][RISCV] vsetivli and vsetvli act as instruments

Since the LMUL data that is needed to create an instrument is
avaliable statically from vsetivli and vsetvli instructions,
LMUL instruments can be automatically generated so that clients
of the tool do no need to manually insert instrument comments.

Instrument comments may be placed after a vset{i}vli instruction,
which will override instrument that was automatically inserted.
As a result, clients of llvm-mca instruments do not need to update
their existing instrument comments. However, if the instrument
has the same LMUL as the vset{i}vli, then it is reccomended to
remove the instrument comment as it becomes redundant.

Differential Revision: https://reviews.llvm.org/D154526
This commit is contained in:
Michael Maitland 2023-07-05 10:04:06 -07:00
parent aef6d4610f
commit ecf372f993
10 changed files with 364 additions and 47 deletions

View File

@ -156,9 +156,16 @@ public:
// Instrument.Desc equal to Type
virtual bool supportsInstrumentType(StringRef Type) const { return false; }
/// Allocate an Instrument, and return a unique pointer to it.
/// Allocate an Instrument, and return a unique pointer to it. This function
/// may be useful to create instruments coming from comments in the assembly.
/// See createInstruments to create Instruments from MCInst
virtual UniqueInstrument createInstrument(StringRef Desc, StringRef Data);
/// Return a list of unique pointers to Instruments, where each Instrument
/// is allocated by this function. See createInstrument to create Instrument
/// from a description and data.
virtual SmallVector<UniqueInstrument> createInstruments(const MCInst &Inst);
/// Given an MCInst and a vector of Instrument, a target can
/// return a SchedClassID. This can be used by a subtarget to return a
/// PseudoInstruction SchedClassID instead of the one that belongs to the

View File

@ -47,6 +47,11 @@ UniqueInstrument InstrumentManager::createInstrument(llvm::StringRef Desc,
return std::make_unique<Instrument>(Desc, Data);
}
SmallVector<UniqueInstrument>
InstrumentManager::createInstruments(const MCInst &Inst) {
return SmallVector<UniqueInstrument>();
}
unsigned InstrumentManager::getSchedClassID(
const MCInstrInfo &MCII, const MCInst &MCI,
const llvm::SmallVector<Instrument *> &IVec) const {

View File

@ -13,6 +13,7 @@
#include "RISCVCustomBehaviour.h"
#include "MCTargetDesc/RISCVMCTargetDesc.h"
#include "RISCV.h"
#include "RISCVInstrInfo.h"
#include "TargetInfo/RISCVTargetInfo.h"
#include "llvm/MC/TargetRegistry.h"
@ -89,6 +90,49 @@ RISCVInstrumentManager::createInstrument(llvm::StringRef Desc,
return std::make_unique<RISCVLMULInstrument>(Data);
}
SmallVector<UniqueInstrument>
RISCVInstrumentManager::createInstruments(const MCInst &Inst) {
if (Inst.getOpcode() == RISCV::VSETVLI ||
Inst.getOpcode() == RISCV::VSETIVLI) {
LLVM_DEBUG(dbgs() << "RVCB: Found VSETVLI and creating instrument for it: "
<< Inst << "\n");
unsigned VTypeI = Inst.getOperand(2).getImm();
RISCVII::VLMUL VLMUL = RISCVVType::getVLMUL(VTypeI);
StringRef LMUL;
switch (VLMUL) {
case RISCVII::LMUL_1:
LMUL = "M1";
break;
case RISCVII::LMUL_2:
LMUL = "M2";
break;
case RISCVII::LMUL_4:
LMUL = "M4";
break;
case RISCVII::LMUL_8:
LMUL = "M8";
break;
case RISCVII::LMUL_F2:
LMUL = "MF2";
break;
case RISCVII::LMUL_F4:
LMUL = "MF4";
break;
case RISCVII::LMUL_F8:
LMUL = "MF8";
break;
case RISCVII::LMUL_RESERVED:
llvm_unreachable("Cannot create instrument for LMUL_RESERVED");
}
SmallVector<UniqueInstrument> Instruments;
Instruments.emplace_back(
createInstrument(RISCVLMULInstrument::DESC_NAME, LMUL));
return Instruments;
}
return SmallVector<UniqueInstrument>();
}
unsigned RISCVInstrumentManager::getSchedClassID(
const MCInstrInfo &MCII, const MCInst &MCI,
const llvm::SmallVector<Instrument *> &IVec) const {

View File

@ -49,6 +49,8 @@ public:
/// Create a Instrument for RISC-V target
UniqueInstrument createInstrument(StringRef Desc, StringRef Data) override;
SmallVector<UniqueInstrument> createInstruments(const MCInst &Inst) override;
/// Using the Instrument, returns a SchedClassID to use instead of
/// the SchedClassID that belongs to the MCI or the original SchedClassID.
unsigned

View File

@ -0,0 +1,69 @@
# NOTE: Assertions have been autogenerated by utils/update_mca_test_checks.py
# RUN: llvm-mca -mtriple=riscv64 -mcpu=sifive-x280 -timeline -iterations=1 < %s | FileCheck %s
vadd.vv v12, v12, v12
vsetvli zero, a0, e8, m1, tu, mu
vadd.vv v12, v12, v12
# CHECK: Iterations: 1
# CHECK-NEXT: Instructions: 3
# CHECK-NEXT: Total Cycles: 21
# CHECK-NEXT: Total uOps: 3
# CHECK: Dispatch Width: 2
# CHECK-NEXT: uOps Per Cycle: 0.14
# CHECK-NEXT: IPC: 0.14
# CHECK-NEXT: Block RThroughput: 18.0
# CHECK: Instruction Info:
# CHECK-NEXT: [1]: #uOps
# CHECK-NEXT: [2]: Latency
# CHECK-NEXT: [3]: RThroughput
# CHECK-NEXT: [4]: MayLoad
# CHECK-NEXT: [5]: MayStore
# CHECK-NEXT: [6]: HasSideEffects (U)
# CHECK: [1] [2] [3] [4] [5] [6] Instructions:
# CHECK-NEXT: 1 4 16.00 vadd.vv v12, v12, v12
# CHECK-NEXT: 1 3 1.00 U vsetvli zero, a0, e8, m1, tu, mu
# CHECK-NEXT: 1 4 2.00 vadd.vv v12, v12, v12
# CHECK: Resources:
# CHECK-NEXT: [0] - SiFive7FDiv
# CHECK-NEXT: [1] - SiFive7IDiv
# CHECK-NEXT: [2] - SiFive7PipeA
# CHECK-NEXT: [3] - SiFive7PipeB
# CHECK-NEXT: [4] - SiFive7PipeV
# CHECK-NEXT: [5] - SiFive7VA
# CHECK-NEXT: [6] - SiFive7VL
# CHECK-NEXT: [7] - SiFive7VS
# CHECK: Resource pressure per iteration:
# CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6] [7]
# CHECK-NEXT: - - 1.00 - 18.00 18.00 - -
# CHECK: Resource pressure by instruction:
# CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6] [7] Instructions:
# CHECK-NEXT: - - - - 16.00 16.00 - - vadd.vv v12, v12, v12
# CHECK-NEXT: - - 1.00 - - - - - vsetvli zero, a0, e8, m1, tu, mu
# CHECK-NEXT: - - - - 2.00 2.00 - - vadd.vv v12, v12, v12
# CHECK: Timeline view:
# CHECK-NEXT: 0123456789
# CHECK-NEXT: Index 0123456789 0
# CHECK: [0,0] DeeeE. . . . vadd.vv v12, v12, v12
# CHECK-NEXT: [0,1] .DeeE. . . . vsetvli zero, a0, e8, m1, tu, mu
# CHECK-NEXT: [0,2] . . . .DeeeE vadd.vv v12, v12, v12
# CHECK: Average Wait times (based on the timeline view):
# CHECK-NEXT: [0]: Executions
# CHECK-NEXT: [1]: Average time spent waiting in a scheduler's queue
# CHECK-NEXT: [2]: Average time spent waiting in a scheduler's queue while ready
# CHECK-NEXT: [3]: Average time elapsed from WB until retire stage
# CHECK: [0] [1] [2] [3]
# CHECK-NEXT: 0. 1 0.0 0.0 0.0 vadd.vv v12, v12, v12
# CHECK-NEXT: 1. 1 0.0 0.0 0.0 vsetvli zero, a0, e8, m1, tu, mu
# CHECK-NEXT: 2. 1 0.0 0.0 0.0 vadd.vv v12, v12, v12
# CHECK-NEXT: 1 0.0 0.0 0.0 <total>

View File

@ -0,0 +1,74 @@
# NOTE: Assertions have been autogenerated by utils/update_mca_test_checks.py
# RUN: llvm-mca -mtriple=riscv64 -mcpu=sifive-x280 -timeline -iterations=1 < %s | FileCheck %s
vsetivli zero, 8, e8, m1, tu, mu
vadd.vv v12, v12, v12
vsetivli zero, 8, e8, m8, tu, mu
vadd.vv v12, v12, v12
# CHECK: Iterations: 1
# CHECK-NEXT: Instructions: 4
# CHECK-NEXT: Total Cycles: 12
# CHECK-NEXT: Total uOps: 4
# CHECK: Dispatch Width: 2
# CHECK-NEXT: uOps Per Cycle: 0.33
# CHECK-NEXT: IPC: 0.33
# CHECK-NEXT: Block RThroughput: 18.0
# CHECK: Instruction Info:
# CHECK-NEXT: [1]: #uOps
# CHECK-NEXT: [2]: Latency
# CHECK-NEXT: [3]: RThroughput
# CHECK-NEXT: [4]: MayLoad
# CHECK-NEXT: [5]: MayStore
# CHECK-NEXT: [6]: HasSideEffects (U)
# CHECK: [1] [2] [3] [4] [5] [6] Instructions:
# CHECK-NEXT: 1 3 1.00 U vsetivli zero, 8, e8, m1, tu, mu
# CHECK-NEXT: 1 4 2.00 vadd.vv v12, v12, v12
# CHECK-NEXT: 1 3 1.00 U vsetivli zero, 8, e8, m8, tu, mu
# CHECK-NEXT: 1 4 16.00 vadd.vv v12, v12, v12
# CHECK: Resources:
# CHECK-NEXT: [0] - SiFive7FDiv
# CHECK-NEXT: [1] - SiFive7IDiv
# CHECK-NEXT: [2] - SiFive7PipeA
# CHECK-NEXT: [3] - SiFive7PipeB
# CHECK-NEXT: [4] - SiFive7PipeV
# CHECK-NEXT: [5] - SiFive7VA
# CHECK-NEXT: [6] - SiFive7VL
# CHECK-NEXT: [7] - SiFive7VS
# CHECK: Resource pressure per iteration:
# CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6] [7]
# CHECK-NEXT: - - 2.00 - 18.00 18.00 - -
# CHECK: Resource pressure by instruction:
# CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6] [7] Instructions:
# CHECK-NEXT: - - 1.00 - - - - - vsetivli zero, 8, e8, m1, tu, mu
# CHECK-NEXT: - - - - 2.00 2.00 - - vadd.vv v12, v12, v12
# CHECK-NEXT: - - 1.00 - - - - - vsetivli zero, 8, e8, m8, tu, mu
# CHECK-NEXT: - - - - 16.00 16.00 - - vadd.vv v12, v12, v12
# CHECK: Timeline view:
# CHECK-NEXT: 01
# CHECK-NEXT: Index 0123456789
# CHECK: [0,0] DeeE . .. vsetivli zero, 8, e8, m1, tu, mu
# CHECK-NEXT: [0,1] . DeeeE .. vadd.vv v12, v12, v12
# CHECK-NEXT: [0,2] . DeeE .. vsetivli zero, 8, e8, m8, tu, mu
# CHECK-NEXT: [0,3] . . DeeeE vadd.vv v12, v12, v12
# CHECK: Average Wait times (based on the timeline view):
# CHECK-NEXT: [0]: Executions
# CHECK-NEXT: [1]: Average time spent waiting in a scheduler's queue
# CHECK-NEXT: [2]: Average time spent waiting in a scheduler's queue while ready
# CHECK-NEXT: [3]: Average time elapsed from WB until retire stage
# CHECK: [0] [1] [2] [3]
# CHECK-NEXT: 0. 1 0.0 0.0 0.0 vsetivli zero, 8, e8, m1, tu, mu
# CHECK-NEXT: 1. 1 0.0 0.0 0.0 vadd.vv v12, v12, v12
# CHECK-NEXT: 2. 1 0.0 0.0 0.0 vsetivli zero, 8, e8, m8, tu, mu
# CHECK-NEXT: 3. 1 0.0 0.0 0.0 vadd.vv v12, v12, v12
# CHECK-NEXT: 1 0.0 0.0 0.0 <total>

View File

@ -0,0 +1,74 @@
# NOTE: Assertions have been autogenerated by utils/update_mca_test_checks.py
# RUN: llvm-mca -mtriple=riscv64 -mcpu=sifive-x280 -timeline -iterations=1 < %s | FileCheck %s
vsetvli zero, a0, e8, m1, tu, mu
vadd.vv v12, v12, v12
vsetvli zero, a0, e8, m8, tu, mu
vadd.vv v12, v12, v12
# CHECK: Iterations: 1
# CHECK-NEXT: Instructions: 4
# CHECK-NEXT: Total Cycles: 12
# CHECK-NEXT: Total uOps: 4
# CHECK: Dispatch Width: 2
# CHECK-NEXT: uOps Per Cycle: 0.33
# CHECK-NEXT: IPC: 0.33
# CHECK-NEXT: Block RThroughput: 18.0
# CHECK: Instruction Info:
# CHECK-NEXT: [1]: #uOps
# CHECK-NEXT: [2]: Latency
# CHECK-NEXT: [3]: RThroughput
# CHECK-NEXT: [4]: MayLoad
# CHECK-NEXT: [5]: MayStore
# CHECK-NEXT: [6]: HasSideEffects (U)
# CHECK: [1] [2] [3] [4] [5] [6] Instructions:
# CHECK-NEXT: 1 3 1.00 U vsetvli zero, a0, e8, m1, tu, mu
# CHECK-NEXT: 1 4 2.00 vadd.vv v12, v12, v12
# CHECK-NEXT: 1 3 1.00 U vsetvli zero, a0, e8, m8, tu, mu
# CHECK-NEXT: 1 4 16.00 vadd.vv v12, v12, v12
# CHECK: Resources:
# CHECK-NEXT: [0] - SiFive7FDiv
# CHECK-NEXT: [1] - SiFive7IDiv
# CHECK-NEXT: [2] - SiFive7PipeA
# CHECK-NEXT: [3] - SiFive7PipeB
# CHECK-NEXT: [4] - SiFive7PipeV
# CHECK-NEXT: [5] - SiFive7VA
# CHECK-NEXT: [6] - SiFive7VL
# CHECK-NEXT: [7] - SiFive7VS
# CHECK: Resource pressure per iteration:
# CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6] [7]
# CHECK-NEXT: - - 2.00 - 18.00 18.00 - -
# CHECK: Resource pressure by instruction:
# CHECK-NEXT: [0] [1] [2] [3] [4] [5] [6] [7] Instructions:
# CHECK-NEXT: - - 1.00 - - - - - vsetvli zero, a0, e8, m1, tu, mu
# CHECK-NEXT: - - - - 2.00 2.00 - - vadd.vv v12, v12, v12
# CHECK-NEXT: - - 1.00 - - - - - vsetvli zero, a0, e8, m8, tu, mu
# CHECK-NEXT: - - - - 16.00 16.00 - - vadd.vv v12, v12, v12
# CHECK: Timeline view:
# CHECK-NEXT: 01
# CHECK-NEXT: Index 0123456789
# CHECK: [0,0] DeeE . .. vsetvli zero, a0, e8, m1, tu, mu
# CHECK-NEXT: [0,1] . DeeeE .. vadd.vv v12, v12, v12
# CHECK-NEXT: [0,2] . DeeE .. vsetvli zero, a0, e8, m8, tu, mu
# CHECK-NEXT: [0,3] . . DeeeE vadd.vv v12, v12, v12
# CHECK: Average Wait times (based on the timeline view):
# CHECK-NEXT: [0]: Executions
# CHECK-NEXT: [1]: Average time spent waiting in a scheduler's queue
# CHECK-NEXT: [2]: Average time spent waiting in a scheduler's queue while ready
# CHECK-NEXT: [3]: Average time elapsed from WB until retire stage
# CHECK: [0] [1] [2] [3]
# CHECK-NEXT: 0. 1 0.0 0.0 0.0 vsetvli zero, a0, e8, m1, tu, mu
# CHECK-NEXT: 1. 1 0.0 0.0 0.0 vadd.vv v12, v12, v12
# CHECK-NEXT: 2. 1 0.0 0.0 0.0 vsetvli zero, a0, e8, m8, tu, mu
# CHECK-NEXT: 3. 1 0.0 0.0 0.0 vadd.vv v12, v12, v12
# CHECK-NEXT: 1 0.0 0.0 0.0 <total>

View File

@ -172,22 +172,30 @@ public:
bool isRegionActive(llvm::StringRef Description) const {
return ActiveRegions.contains(Description);
}
virtual void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc) = 0;
virtual void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc,
UniqueInstrument Instrument) = 0;
virtual void endRegion(llvm::StringRef Description, llvm::SMLoc Loc) = 0;
};
struct AnalysisRegions : public CodeRegions {
AnalysisRegions(llvm::SourceMgr &S);
void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc);
void endRegion(llvm::StringRef Description, llvm::SMLoc Loc);
void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc) override;
void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc,
UniqueInstrument Instrument) override {}
void endRegion(llvm::StringRef Description, llvm::SMLoc Loc) override;
};
struct InstrumentRegions : public CodeRegions {
InstrumentRegions(llvm::SourceMgr &S);
void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc) override{};
void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc,
UniqueInstrument Instrument);
void endRegion(llvm::StringRef Description, llvm::SMLoc Loc);
UniqueInstrument Instrument) override;
void endRegion(llvm::StringRef Description, llvm::SMLoc Loc) override;
const SmallVector<Instrument *> getActiveInstruments(llvm::SMLoc Loc) const;
};

View File

@ -17,7 +17,6 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/MC/MCParser/MCTargetAsmParser.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCTargetOptions.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/SMLoc.h"
@ -29,46 +28,12 @@ namespace mca {
// This virtual dtor serves as the anchor for the CodeRegionGenerator class.
CodeRegionGenerator::~CodeRegionGenerator() {}
// This class provides the callbacks that occur when parsing input assembly.
class MCStreamerWrapper final : public MCStreamer {
CodeRegions &Regions;
public:
MCStreamerWrapper(MCContext &Context, mca::CodeRegions &R)
: MCStreamer(Context), Regions(R) {}
// We only want to intercept the emission of new instructions.
void emitInstruction(const MCInst &Inst,
const MCSubtargetInfo & /* unused */) override {
Regions.addInstruction(Inst);
}
bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override {
return true;
}
void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
Align ByteAlignment) override {}
void emitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,
uint64_t Size = 0, Align ByteAlignment = Align(1),
SMLoc Loc = SMLoc()) override {}
void emitGPRel32Value(const MCExpr *Value) override {}
void beginCOFFSymbolDef(const MCSymbol *Symbol) override {}
void emitCOFFSymbolStorageClass(int StorageClass) override {}
void emitCOFFSymbolType(int Type) override {}
void endCOFFSymbolDef() override {}
ArrayRef<MCInst> GetInstructionSequence(unsigned Index) const {
return Regions.getInstructionSequence(Index);
}
};
Expected<const CodeRegions &> AsmCodeRegionGenerator::parseCodeRegions(
const std::unique_ptr<MCInstPrinter> &IP) {
MCTargetOptions Opts;
Opts.PreserveAsmComments = false;
CodeRegions &Regions = getRegions();
MCStreamerWrapper Str(Ctx, Regions);
MCStreamerWrapper *Str = getMCStreamer();
// Need to initialize an MCTargetStreamer otherwise
// certain asm directives will cause a segfault.
@ -76,13 +41,13 @@ Expected<const CodeRegions &> AsmCodeRegionGenerator::parseCodeRegions(
// doesn't show up in the llvm-mca output.
raw_ostream &OSRef = nulls();
formatted_raw_ostream FOSRef(OSRef);
TheTarget.createAsmTargetStreamer(Str, FOSRef, IP.get(),
TheTarget.createAsmTargetStreamer(*Str, FOSRef, IP.get(),
/*IsVerboseAsm=*/true);
// Create a MCAsmParser and setup the lexer to recognize llvm-mca ASM
// comments.
std::unique_ptr<MCAsmParser> Parser(
createMCAsmParser(Regions.getSourceMgr(), Ctx, Str, MAI));
createMCAsmParser(Regions.getSourceMgr(), Ctx, *Str, MAI));
MCAsmLexer &Lexer = Parser->getLexer();
MCACommentConsumer *CCP = getCommentConsumer();
Lexer.setCommentConsumer(CCP);

View File

@ -20,6 +20,7 @@
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCParser/MCAsmLexer.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/MCA/CustomBehaviour.h"
@ -77,6 +78,67 @@ public:
/// region of type INSTRUMENATION_TYPE, then it will end the active
/// one and begin a new one using the new data.
void HandleComment(SMLoc Loc, StringRef CommentText) override;
InstrumentManager &getInstrumentManager() { return IM; }
};
// This class provides the callbacks that occur when parsing input assembly.
class MCStreamerWrapper : public MCStreamer {
protected:
CodeRegions &Regions;
public:
MCStreamerWrapper(MCContext &Context, mca::CodeRegions &R)
: MCStreamer(Context), Regions(R) {}
// We only want to intercept the emission of new instructions.
void emitInstruction(const MCInst &Inst,
const MCSubtargetInfo & /* unused */) override {
Regions.addInstruction(Inst);
}
bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override {
return true;
}
void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
Align ByteAlignment) override {}
void emitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,
uint64_t Size = 0, Align ByteAlignment = Align(1),
SMLoc Loc = SMLoc()) override {}
void emitGPRel32Value(const MCExpr *Value) override {}
void beginCOFFSymbolDef(const MCSymbol *Symbol) override {}
void emitCOFFSymbolStorageClass(int StorageClass) override {}
void emitCOFFSymbolType(int Type) override {}
void endCOFFSymbolDef() override {}
ArrayRef<MCInst> GetInstructionSequence(unsigned Index) const {
return Regions.getInstructionSequence(Index);
}
};
class InstrumentMCStreamer : public MCStreamerWrapper {
InstrumentManager &IM;
public:
InstrumentMCStreamer(MCContext &Context, mca::InstrumentRegions &R,
InstrumentManager &IM)
: MCStreamerWrapper(Context, R), IM(IM) {}
void emitInstruction(const MCInst &Inst,
const MCSubtargetInfo &MCSI) override {
MCStreamerWrapper::emitInstruction(Inst, MCSI);
// We know that Regions is an InstrumentRegions by the constructor.
for (UniqueInstrument &I : IM.createInstruments(Inst)) {
StringRef InstrumentKind = I.get()->getDesc();
// End InstrumentType region if one is open
if (Regions.isRegionActive(InstrumentKind))
Regions.endRegion(InstrumentKind, Inst.getLoc());
// Start new instrumentation region
Regions.beginRegion(InstrumentKind, Inst.getLoc(), std::move(I));
}
}
};
/// This abstract class is responsible for parsing the input given to
@ -121,19 +183,22 @@ public:
/// generating a CodeRegions instance.
class AsmCodeRegionGenerator : public virtual CodeRegionGenerator {
const Target &TheTarget;
MCContext &Ctx;
const MCAsmInfo &MAI;
const MCSubtargetInfo &STI;
const MCInstrInfo &MCII;
unsigned AssemblerDialect; // This is set during parsing.
protected:
MCContext &Ctx;
public:
AsmCodeRegionGenerator(const Target &T, MCContext &C, const MCAsmInfo &A,
const MCSubtargetInfo &S, const MCInstrInfo &I)
: TheTarget(T), Ctx(C), MAI(A), STI(S), MCII(I), AssemblerDialect(0) {}
: TheTarget(T), MAI(A), STI(S), MCII(I), AssemblerDialect(0), Ctx(C) {}
virtual MCACommentConsumer *getCommentConsumer() = 0;
virtual CodeRegions &getRegions() = 0;
virtual MCStreamerWrapper *getMCStreamer() = 0;
unsigned getAssemblerDialect() const { return AssemblerDialect; }
Expected<const CodeRegions &>
@ -143,16 +208,18 @@ public:
class AsmAnalysisRegionGenerator final : public AnalysisRegionGenerator,
public AsmCodeRegionGenerator {
AnalysisRegionCommentConsumer CC;
MCStreamerWrapper Streamer;
public:
AsmAnalysisRegionGenerator(const Target &T, llvm::SourceMgr &SM, MCContext &C,
const MCAsmInfo &A, const MCSubtargetInfo &S,
const MCInstrInfo &I)
: AnalysisRegionGenerator(SM), AsmCodeRegionGenerator(T, C, A, S, I),
CC(Regions) {}
CC(Regions), Streamer(Ctx, Regions) {}
MCACommentConsumer *getCommentConsumer() override { return &CC; };
CodeRegions &getRegions() override { return Regions; };
MCStreamerWrapper *getMCStreamer() override { return &Streamer; }
Expected<const AnalysisRegions &>
parseAnalysisRegions(const std::unique_ptr<MCInstPrinter> &IP) override {
@ -172,6 +239,7 @@ public:
class AsmInstrumentRegionGenerator final : public InstrumentRegionGenerator,
public AsmCodeRegionGenerator {
InstrumentRegionCommentConsumer CC;
InstrumentMCStreamer Streamer;
public:
AsmInstrumentRegionGenerator(const Target &T, llvm::SourceMgr &SM,
@ -179,10 +247,11 @@ public:
const MCSubtargetInfo &S, const MCInstrInfo &I,
InstrumentManager &IM)
: InstrumentRegionGenerator(SM), AsmCodeRegionGenerator(T, C, A, S, I),
CC(SM, Regions, IM) {}
CC(SM, Regions, IM), Streamer(Ctx, Regions, IM) {}
MCACommentConsumer *getCommentConsumer() override { return &CC; };
CodeRegions &getRegions() override { return Regions; };
MCStreamerWrapper *getMCStreamer() override { return &Streamer; }
Expected<const InstrumentRegions &>
parseInstrumentRegions(const std::unique_ptr<MCInstPrinter> &IP) override {