diff --git a/llvm/include/llvm/MCA/CustomBehaviour.h b/llvm/include/llvm/MCA/CustomBehaviour.h --- a/llvm/include/llvm/MCA/CustomBehaviour.h +++ b/llvm/include/llvm/MCA/CustomBehaviour.h @@ -156,9 +156,16 @@ // 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 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 diff --git a/llvm/lib/MCA/CustomBehaviour.cpp b/llvm/lib/MCA/CustomBehaviour.cpp --- a/llvm/lib/MCA/CustomBehaviour.cpp +++ b/llvm/lib/MCA/CustomBehaviour.cpp @@ -47,6 +47,11 @@ return std::make_unique(Desc, Data); } +SmallVector +InstrumentManager::createInstruments(const MCInst &Inst) { + return SmallVector(); +} + unsigned InstrumentManager::getSchedClassID( const MCInstrInfo &MCII, const MCInst &MCI, const llvm::SmallVector &IVec) const { diff --git a/llvm/lib/Target/RISCV/MCA/RISCVCustomBehaviour.h b/llvm/lib/Target/RISCV/MCA/RISCVCustomBehaviour.h --- a/llvm/lib/Target/RISCV/MCA/RISCVCustomBehaviour.h +++ b/llvm/lib/Target/RISCV/MCA/RISCVCustomBehaviour.h @@ -49,6 +49,8 @@ /// Create a Instrument for RISC-V target UniqueInstrument createInstrument(StringRef Desc, StringRef Data) override; + SmallVector 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 diff --git a/llvm/lib/Target/RISCV/MCA/RISCVCustomBehaviour.cpp b/llvm/lib/Target/RISCV/MCA/RISCVCustomBehaviour.cpp --- a/llvm/lib/Target/RISCV/MCA/RISCVCustomBehaviour.cpp +++ b/llvm/lib/Target/RISCV/MCA/RISCVCustomBehaviour.cpp @@ -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 @@ return std::make_unique(Data); } +SmallVector +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 Instruments; + Instruments.emplace_back( + createInstrument(RISCVLMULInstrument::DESC_NAME, LMUL)); + return Instruments; + } + return SmallVector(); +} + unsigned RISCVInstrumentManager::getSchedClassID( const MCInstrInfo &MCII, const MCInst &MCI, const llvm::SmallVector &IVec) const { diff --git a/llvm/test/tools/llvm-mca/RISCV/no-vsetvli-to-start.s b/llvm/test/tools/llvm-mca/RISCV/no-vsetvli-to-start.s new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-mca/RISCV/no-vsetvli-to-start.s @@ -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 diff --git a/llvm/test/tools/llvm-mca/RISCV/vsetivli-lmul-instrument.s b/llvm/test/tools/llvm-mca/RISCV/vsetivli-lmul-instrument.s new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-mca/RISCV/vsetivli-lmul-instrument.s @@ -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 diff --git a/llvm/test/tools/llvm-mca/RISCV/vsetvli-lmul-instrument.s b/llvm/test/tools/llvm-mca/RISCV/vsetvli-lmul-instrument.s new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-mca/RISCV/vsetvli-lmul-instrument.s @@ -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 diff --git a/llvm/tools/llvm-mca/CodeRegionGenerator.h b/llvm/tools/llvm-mca/CodeRegionGenerator.h --- a/llvm/tools/llvm-mca/CodeRegionGenerator.h +++ b/llvm/tools/llvm-mca/CodeRegionGenerator.h @@ -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,68 @@ /// 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 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. + InstrumentRegions *IR = static_cast(Regions); + for (UniqueInstrument &I : IM.createInstruments(Inst)) { + StringRef InstrumentKind = I.get()->getDesc(); + // End InstrumentType region if one is open + if (IR->isRegionActive(InstrumentKind)) + IR->endRegion(InstrumentKind, Inst.getLoc()); + // Start new instrumentation region + IR->beginRegion(InstrumentKind, Inst.getLoc(), std::move(I)); + } + } }; /// This abstract class is responsible for parsing the input given to @@ -121,19 +184,22 @@ /// 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 @@ -143,16 +209,18 @@ 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 parseAnalysisRegions(const std::unique_ptr &IP) override { @@ -172,6 +240,7 @@ class AsmInstrumentRegionGenerator final : public InstrumentRegionGenerator, public AsmCodeRegionGenerator { InstrumentRegionCommentConsumer CC; + InstrumentMCStreamer Streamer; public: AsmInstrumentRegionGenerator(const Target &T, llvm::SourceMgr &SM, @@ -179,10 +248,11 @@ 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 parseInstrumentRegions(const std::unique_ptr &IP) override { diff --git a/llvm/tools/llvm-mca/CodeRegionGenerator.cpp b/llvm/tools/llvm-mca/CodeRegionGenerator.cpp --- a/llvm/tools/llvm-mca/CodeRegionGenerator.cpp +++ b/llvm/tools/llvm-mca/CodeRegionGenerator.cpp @@ -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 @@ // 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 GetInstructionSequence(unsigned Index) const { - return Regions.getInstructionSequence(Index); - } -}; - Expected AsmCodeRegionGenerator::parseCodeRegions( const std::unique_ptr &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 @@ // 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 Parser( - createMCAsmParser(Regions.getSourceMgr(), Ctx, Str, MAI)); + createMCAsmParser(Regions.getSourceMgr(), Ctx, *Str, MAI)); MCAsmLexer &Lexer = Parser->getLexer(); MCACommentConsumer *CCP = getCommentConsumer(); Lexer.setCommentConsumer(CCP);