detect any custom hazards or make any post processing modifications to
instructions.
-.. option:: -disable-im
-
- Force usage of the generic InstrumentManager rather than using the target
- specific implementation. The generic class creates Instruments that provide
- no extra information, and InstrumentManager never overrides the default
- schedule class for a given instruction.
EXIT STATUS
-----------
---------------------------------------------
:program:`llvm-mca` allows for the optional usage of special code comments to
mark regions of the assembly code to be analyzed. A comment starting with
-substring ``LLVM-MCA-BEGIN`` marks the beginning of an analysis region. A
-comment starting with substring ``LLVM-MCA-END`` marks the end of a region.
-For example:
+substring ``LLVM-MCA-BEGIN`` marks the beginning of a code region. A comment
+starting with substring ``LLVM-MCA-END`` marks the end of a code region. For
+example:
.. code-block:: none
If no user-defined region is specified, then :program:`llvm-mca` assumes a
default region which contains every instruction in the input file. Every region
is analyzed in isolation, and the final performance report is the union of all
-the reports generated for every analysis region.
+the reports generated for every code region.
-Analysis regions can have names. For example:
+Code regions can have names. For example:
.. code-block:: none
The `Clang options to emit optimization reports <https://clang.llvm.org/docs/UsersManual.html#options-to-emit-optimization-reports>`_
can also help in detecting missed optimizations.
-INSTRUMENT REGIONS
-------------------
-
-An InstrumentRegion describes a region of assembly code guarded by
-special LLVM-MCA comment directives.
-
-.. code-block:: none
-
- # LLVM-MCA-<INSTRUMENT_TYPE> <data>
- ... ## asm
-
-where `INSTRUMENT_TYPE` is a type defined by the target and expects
-to use `data`.
-
-A comment starting with substring `LLVM-MCA-<INSTRUMENT_TYPE>`
-brings data into scope for llvm-mca to use in its analysis for
-all following instructions.
-
-If a comment with the same `INSTRUMENT_TYPE` is found later in the
-instruction list, then the original InstrumentRegion will be
-automatically ended, and a new InstrumentRegion will begin.
-
-If there are comments containing the different `INSTRUMENT_TYPE`,
-then both data sets remain available. In contrast with an AnalysisRegion,
-an InstrumentRegion does not need a comment to end the region.
-
-Comments that are prefixed with `LLVM-MCA-` but do not correspond to
-a valid `INSTRUMENT_TYPE` for the target cause an error, except for
-`BEGIN` and `END`, since those correspond to AnalysisRegions. Comments
-that do not start with `LLVM-MCA-` are ignored by :program `llvm-mca`.
-
-An instruction (a MCInst) is added to an InstrumentRegion R only
-if its location is in range [R.RangeStart, R.RangeEnd].
-
-On RISCV targets, vector instructions have different behaviour depending
-on the LMUL. Code can be instrumented with a comment that takes the
-following form:
-
-.. code-block:: none
-
- # LLVM-MCA-RISCV-LMUL <M1|M2|M4|M8|MF2|MF4|MF8>
-
-The RISCV InstrumentManager will override the schedule class for vector
-instructions to use the scheduling behaviour of its pseudo-instruction
-which is LMUL dependent. It makes sense to place RISCV instrument
-comments directly after `vset{i}vl{i}` instructions, although
-they can be placed anywhere in the program.
-
-Example of program with no call to `vset{i}vl{i}`:
-
-.. code-block:: none
-
- # LLVM-MCA-RISCV-LMUL M2
- vadd.vv v2, v2, v2
-
-Example of program with call to `vset{i}vl{i}`:
-
-.. code-block:: none
-
- vsetvli zero, a0, e8, m1, tu, mu
- # LLVM-MCA-RISCV-LMUL M1
- vadd.vv v2, v2, v2
-
-Example of program with multiple calls to `vset{i}vl{i}`:
-
-.. code-block:: none
-
- vsetvli zero, a0, e8, m1, tu, mu
- # LLVM-MCA-RISCV-LMUL M1
- vadd.vv v2, v2, v2
- vsetvli zero, a0, e8, m8, tu, mu
- # LLVM-MCA-RISCV-LMUL M8
- vadd.vv v2, v2, v2
-
-Example of program with call to `vsetvl`:
-
-.. code-block:: none
-
- vsetvl rd, rs1, rs2
- # LLVM-MCA-RISCV-LMUL M1
- vadd.vv v12, v12, v12
- vsetvl rd, rs1, rs2
- # LLVM-MCA-RISCV-LMUL M4
- vadd.vv v12, v12, v12
-
HOW LLVM-MCA WORKS
------------------
up. The classes are implemented within the target specific backend (for
example `/llvm/lib/Target/AMDGPU/MCA/`) so that they can access backend symbols.
-Instrument Manager
-""""""""""""""""""""""""""""""""""""
-On certain architectures, scheduling information for certain instructions
-do not contain all of the information required to identify the most precise
-schedule class. For example, data that can have an impact on scheduling can
-be stored in CSR registers.
-
-One example of this is on RISCV, where values in registers such as `vtype`
-and `vl` change the scheduling behaviour of vector instructions. Since MCA
-does not keep track of the values in registers, instrument comments can
-be used to specify these values.
-
-InstrumentManager's main function is `getSchedClassID()` which has access
-to the MCInst and all of the instruments that are active for that MCInst.
-This function can use the instruments to override the schedule class of
-the MCInst.
-
-On RISCV, instrument comments containing LMUL information are used
-by `getSchedClassID()` to map a vector instruction and the active
-LMUL to the scheduling class of the pseudo-instruction that describes
-that base instruction and the active LMUL.
-
Custom Views
""""""""""""""""""""""""""""""""""""
:program:`llvm-mca` comes with several Views such as the Timeline View and
namespace mca {
class CustomBehaviour;
class InstrPostProcess;
-class InstrumentManager;
struct SourceMgr;
} // namespace mca
mca::InstrPostProcess *createInstrPostProcess(const MCSubtargetInfo &STI,
const MCInstrInfo &MCII);
-mca::InstrumentManager *createInstrumentManager(const MCSubtargetInfo &STI,
- const MCInstrInfo &MCII);
-
/// Target - Wrapper for Target specific information.
///
/// For registration purposes, this is a POD type so that targets can be
mca::InstrPostProcess *(*)(const MCSubtargetInfo &STI,
const MCInstrInfo &MCII);
- using InstrumentManagerCtorTy =
- mca::InstrumentManager *(*)(const MCSubtargetInfo &STI,
- const MCInstrInfo &MCII);
-
private:
/// Next - The next registered target in the linked list, maintained by the
/// TargetRegistry.
/// InstrPostProcess, if registered (default = nullptr).
InstrPostProcessCtorTy InstrPostProcessCtorFn = nullptr;
- /// InstrumentManagerCtorFn - Construction function for this target's
- /// InstrumentManager, if registered (default = nullptr).
- InstrumentManagerCtorTy InstrumentManagerCtorFn = nullptr;
-
public:
Target() = default;
return nullptr;
}
- /// createInstrumentManager - Create a target specific
- /// InstrumentManager. This class is used by llvm-mca and requires
- /// backend functionality.
- mca::InstrumentManager *
- createInstrumentManager(const MCSubtargetInfo &STI,
- const MCInstrInfo &MCII) const {
- if (InstrumentManagerCtorFn)
- return InstrumentManagerCtorFn(STI, MCII);
- return nullptr;
- }
-
/// @}
};
T.InstrPostProcessCtorFn = Fn;
}
- /// RegisterInstrumentManager - Register an InstrumentManager
- /// implementation for the given target.
- ///
- /// Clients are responsible for ensuring that registration doesn't occur
- /// while another thread is attempting to access the registry. Typically
- /// this is done by initializing all targets at program startup.
- ///
- /// @param T - The target being registered.
- /// @param Fn - A function to construct an InstrumentManager for the
- /// target.
- static void RegisterInstrumentManager(Target &T,
- Target::InstrumentManagerCtorTy Fn) {
- T.InstrumentManagerCtorFn = Fn;
- }
-
/// @}
};
#ifndef LLVM_MCA_CUSTOMBEHAVIOUR_H
#define LLVM_MCA_CUSTOMBEHAVIOUR_H
-#include "llvm/ADT/SmallVector.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
getEndViews(llvm::MCInstPrinter &IP, llvm::ArrayRef<llvm::MCInst> Insts);
};
-class Instrument {
- /// The description of Instrument kind
- const StringRef Desc;
-
- /// The instrumentation data
- const StringRef Data;
-
-public:
- Instrument(StringRef Desc, StringRef Data) : Desc(Desc), Data(Data) {}
-
- Instrument() = default;
-
- virtual ~Instrument() = default;
-
- StringRef getDesc() const { return Desc; }
- StringRef getData() const { return Data; }
-};
-
-using SharedInstrument = std::shared_ptr<Instrument>;
-
-/// This class allows targets to optionally customize the logic that resolves
-/// scheduling class IDs. Targets can use information encoded in Instrument
-/// objects to make more informed scheduling decisions.
-class InstrumentManager {
-protected:
- const MCSubtargetInfo &STI;
- const MCInstrInfo &MCII;
-
-public:
- InstrumentManager(const MCSubtargetInfo &STI, const MCInstrInfo &MCII)
- : STI(STI), MCII(MCII) {}
-
- virtual ~InstrumentManager() = default;
-
- /// Returns true if llvm-mca should ignore instruments.
- virtual bool shouldIgnoreInstruments() const { return true; }
-
- // Returns true if this supports processing Instrument with
- // Instrument.Desc equal to Type
- virtual bool supportsInstrumentType(StringRef Type) const { return false; }
-
- /// Allocate an Instrument, and return a shared pointer to it.
- virtual SharedInstrument createInstrument(StringRef Desc, StringRef Data);
-
- /// 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
- /// BaseInstruction This can be useful when a BaseInstruction does not convey
- /// the correct scheduling information without additional data. By default,
- /// it returns the SchedClassID that belongs to MCI.
- virtual unsigned
- getSchedClassID(const MCInstrInfo &MCII, const MCInst &MCI,
- const SmallVector<SharedInstrument> &IVec) const;
-};
-
} // namespace mca
} // namespace llvm
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
-#include "llvm/MCA/CustomBehaviour.h"
#include "llvm/MCA/Instruction.h"
#include "llvm/MCA/Support.h"
#include "llvm/Support/Error.h"
const MCInstrInfo &MCII;
const MCRegisterInfo &MRI;
const MCInstrAnalysis *MCIA;
- const InstrumentManager &IM;
SmallVector<uint64_t, 8> ProcResourceMasks;
- // Key is the MCI.Opcode and SchedClassID the describe the value InstrDesc
- DenseMap<std::pair<unsigned short, unsigned>,
- std::unique_ptr<const InstrDesc>>
- Descriptors;
-
- // Key is the MCIInst and SchedClassID the describe the value InstrDesc
- DenseMap<std::pair<const MCInst *, unsigned>,
- std::unique_ptr<const InstrDesc>>
- VariantDescriptors;
+ DenseMap<unsigned short, std::unique_ptr<const InstrDesc>> Descriptors;
+ DenseMap<const MCInst *, std::unique_ptr<const InstrDesc>> VariantDescriptors;
bool FirstCallInst;
bool FirstReturnInst;
llvm::function_ref<Instruction *(const InstrDesc &)>;
InstRecycleCallback InstRecycleCB;
- Expected<const InstrDesc &>
- createInstrDescImpl(const MCInst &MCI,
- const SmallVector<SharedInstrument> &IVec);
- Expected<const InstrDesc &>
- getOrCreateInstrDesc(const MCInst &MCI,
- const SmallVector<SharedInstrument> &IVec);
+ Expected<const InstrDesc &> createInstrDescImpl(const MCInst &MCI);
+ Expected<const InstrDesc &> getOrCreateInstrDesc(const MCInst &MCI);
InstrBuilder(const InstrBuilder &) = delete;
InstrBuilder &operator=(const InstrBuilder &) = delete;
public:
InstrBuilder(const MCSubtargetInfo &STI, const MCInstrInfo &MCII,
- const MCRegisterInfo &RI, const MCInstrAnalysis *IA,
- const InstrumentManager &IM);
+ const MCRegisterInfo &RI, const MCInstrAnalysis *IA);
void clear() {
Descriptors.clear();
/// or null if there isn't any.
void setInstRecycleCallback(InstRecycleCallback CB) { InstRecycleCB = CB; }
- Expected<std::unique_ptr<Instruction>>
- createInstruction(const MCInst &MCI,
- const SmallVector<SharedInstrument> &IVec);
+ Expected<std::unique_ptr<Instruction>> createInstruction(const MCInst &MCI);
};
} // namespace mca
} // namespace llvm
return std::vector<std::unique_ptr<View>>();
}
-SharedInstrument InstrumentManager::createInstrument(llvm::StringRef Desc,
- llvm::StringRef Data) {
- return std::make_shared<Instrument>(Desc, Data);
-}
-
-unsigned InstrumentManager::getSchedClassID(
- const MCInstrInfo &MCII, const MCInst &MCI,
- const llvm::SmallVector<SharedInstrument> &IVec) const {
- return MCII.get(MCI.getOpcode()).getSchedClass();
-}
-
} // namespace mca
} // namespace llvm
InstrBuilder::InstrBuilder(const llvm::MCSubtargetInfo &sti,
const llvm::MCInstrInfo &mcii,
const llvm::MCRegisterInfo &mri,
- const llvm::MCInstrAnalysis *mcia,
- const mca::InstrumentManager &im)
- : STI(sti), MCII(mcii), MRI(mri), MCIA(mcia), IM(im), FirstCallInst(true),
+ const llvm::MCInstrAnalysis *mcia)
+ : STI(sti), MCII(mcii), MRI(mri), MCIA(mcia), FirstCallInst(true),
FirstReturnInst(true) {
const MCSchedModel &SM = STI.getSchedModel();
ProcResourceMasks.resize(SM.getNumProcResourceKinds());
}
Expected<const InstrDesc &>
-InstrBuilder::createInstrDescImpl(const MCInst &MCI,
- const SmallVector<SharedInstrument> &IVec) {
+InstrBuilder::createInstrDescImpl(const MCInst &MCI) {
assert(STI.getSchedModel().hasInstrSchedModel() &&
"Itineraries are not yet supported!");
const MCSchedModel &SM = STI.getSchedModel();
// Then obtain the scheduling class information from the instruction.
- // Allow InstrumentManager to override and use a different SchedClassID
- unsigned SchedClassID = IM.getSchedClassID(MCII, MCI, IVec);
+ unsigned SchedClassID = MCDesc.getSchedClass();
bool IsVariant = SM.getSchedClassDesc(SchedClassID)->isVariant();
// Try to solve variant scheduling classes.
// Now add the new descriptor.
bool IsVariadic = MCDesc.isVariadic();
if ((ID->IsRecyclable = !IsVariadic && !IsVariant)) {
- auto DKey = std::make_pair(MCI.getOpcode(), SchedClassID);
- Descriptors[DKey] = std::move(ID);
- return *Descriptors[DKey];
+ Descriptors[MCI.getOpcode()] = std::move(ID);
+ return *Descriptors[MCI.getOpcode()];
}
- auto VDKey = std::make_pair(&MCI, SchedClassID);
- VariantDescriptors[VDKey] = std::move(ID);
- return *VariantDescriptors[VDKey];
+ VariantDescriptors[&MCI] = std::move(ID);
+ return *VariantDescriptors[&MCI];
}
Expected<const InstrDesc &>
-InstrBuilder::getOrCreateInstrDesc(const MCInst &MCI,
- const SmallVector<SharedInstrument> &IVec) {
- // Cache lookup using SchedClassID from Instrumentation
- unsigned SchedClassID = IM.getSchedClassID(MCII, MCI, IVec);
-
- auto DKey = std::make_pair(MCI.getOpcode(), SchedClassID);
- if (Descriptors.find_as(DKey) != Descriptors.end())
- return *Descriptors[DKey];
-
- unsigned CPUID = STI.getSchedModel().getProcessorID();
- SchedClassID = STI.resolveVariantSchedClass(SchedClassID, &MCI, &MCII, CPUID);
- auto VDKey = std::make_pair(&MCI, SchedClassID);
- if (VariantDescriptors.find(VDKey) != VariantDescriptors.end())
- return *VariantDescriptors[VDKey];
-
- return createInstrDescImpl(MCI, IVec);
+InstrBuilder::getOrCreateInstrDesc(const MCInst &MCI) {
+ if (Descriptors.find_as(MCI.getOpcode()) != Descriptors.end())
+ return *Descriptors[MCI.getOpcode()];
+
+ if (VariantDescriptors.find(&MCI) != VariantDescriptors.end())
+ return *VariantDescriptors[&MCI];
+
+ return createInstrDescImpl(MCI);
}
STATISTIC(NumVariantInst, "Number of MCInsts that doesn't have static Desc");
Expected<std::unique_ptr<Instruction>>
-InstrBuilder::createInstruction(const MCInst &MCI,
- const SmallVector<SharedInstrument> &IVec) {
- Expected<const InstrDesc &> DescOrErr = getOrCreateInstrDesc(MCI, IVec);
+InstrBuilder::createInstruction(const MCInst &MCI) {
+ Expected<const InstrDesc &> DescOrErr = getOrCreateInstrDesc(MCI);
if (!DescOrErr)
return DescOrErr.takeError();
const InstrDesc &D = *DescOrErr;
add_subdirectory(AsmParser)
add_subdirectory(Disassembler)
add_subdirectory(MCTargetDesc)
-add_subdirectory(MCA)
add_subdirectory(TargetInfo)
+++ /dev/null
-add_llvm_component_library(LLVMRISCVTargetMCA
- RISCVCustomBehaviour.cpp
-
- LINK_COMPONENTS
- MC
- MCParser
- RISCVDesc
- RISCVInfo
- Support
- MCA
-
- ADD_TO_COMPONENT
- RISCV
- )
+++ /dev/null
-//===------------------- RISCVCustomBehaviour.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
-//
-//===----------------------------------------------------------------------===//
-/// \file
-///
-/// This file implements methods from the RISCVCustomBehaviour class.
-///
-//===----------------------------------------------------------------------===//
-
-#include "RISCVCustomBehaviour.h"
-#include "MCTargetDesc/RISCVMCTargetDesc.h"
-#include "RISCVInstrInfo.h"
-#include "TargetInfo/RISCVTargetInfo.h"
-#include "llvm/MC/TargetRegistry.h"
-#include "llvm/Support/Debug.h"
-
-#define DEBUG_TYPE "llvm-mca-riscv-custombehaviour"
-
-// This brings in a table with primary key of
-// base instruction opcode and lmul and maps
-// to the opcode of the pseudo instruction.
-namespace RISCVVInversePseudosTable {
-using namespace llvm;
-using namespace llvm::RISCV;
-
-struct PseudoInfo {
- uint16_t Pseudo;
- uint16_t BaseInstr;
- uint8_t VLMul;
-};
-
-#define GET_RISCVVInversePseudosTable_IMPL
-#define GET_RISCVVInversePseudosTable_DECL
-#include "RISCVGenSearchableTables.inc"
-
-} // end namespace RISCVVInversePseudosTable
-
-namespace llvm {
-namespace mca {
-
-const llvm::StringRef RISCVLMULInstrument::DESC_NAME = "RISCV-LMUL";
-
-bool RISCVLMULInstrument::isDataValid(llvm::StringRef Data) {
- // Return true if not one of the valid LMUL strings
- return StringSwitch<bool>(Data)
- .Cases("M1", "M2", "M4", "M8", "MF2", "MF4", "MF8", true)
- .Default(false);
-}
-
-uint8_t RISCVLMULInstrument::getLMUL() const {
- // assertion prevents us from needing llvm_unreachable in the StringSwitch
- // below
- assert(isDataValid(getData()) &&
- "Cannot get LMUL because invalid Data value");
- // These are the LMUL values that are used in RISCV tablegen
- return StringSwitch<uint8_t>(getData())
- .Case("M1", 0b000)
- .Case("M2", 0b001)
- .Case("M4", 0b010)
- .Case("M8", 0b011)
- .Case("MF2", 0b101)
- .Case("MF4", 0b110)
- .Case("MF8", 0b111);
-}
-
-bool RISCVInstrumentManager::supportsInstrumentType(
- llvm::StringRef Type) const {
- // Currently, only support for RISCVLMULInstrument type
- return Type == RISCVLMULInstrument::DESC_NAME;
-}
-
-SharedInstrument
-RISCVInstrumentManager::createInstrument(llvm::StringRef Desc,
- llvm::StringRef Data) {
- if (Desc != RISCVLMULInstrument::DESC_NAME) {
- LLVM_DEBUG(dbgs() << "RVCB: Unknown instrumentation Desc: " << Desc
- << '\n');
- return nullptr;
- }
- if (RISCVLMULInstrument::isDataValid(Data)) {
- LLVM_DEBUG(dbgs() << "RVCB: Bad data for instrument kind " << Desc << ": "
- << Data << '\n');
- return nullptr;
- }
- return std::make_shared<RISCVLMULInstrument>(Data);
-}
-
-unsigned RISCVInstrumentManager::getSchedClassID(
- const MCInstrInfo &MCII, const MCInst &MCI,
- const llvm::SmallVector<SharedInstrument> &IVec) const {
- unsigned short Opcode = MCI.getOpcode();
- unsigned SchedClassID = MCII.get(Opcode).getSchedClass();
-
- for (const auto &I : IVec) {
- // Unknown Instrument kind
- if (I->getDesc() == RISCVLMULInstrument::DESC_NAME) {
- uint8_t LMUL = static_cast<RISCVLMULInstrument *>(I.get())->getLMUL();
- const RISCVVInversePseudosTable::PseudoInfo *RVV =
- RISCVVInversePseudosTable::getBaseInfo(Opcode, LMUL);
- // Not a RVV instr
- if (!RVV) {
- LLVM_DEBUG(
- dbgs()
- << "RVCB: Could not find PseudoInstruction for Opcode "
- << MCII.getName(Opcode) << ", LMUL=" << I->getData()
- << ". Ignoring instrumentation and using original SchedClassID="
- << SchedClassID << '\n');
- return SchedClassID;
- }
-
- // Override using pseudo
- LLVM_DEBUG(dbgs() << "RVCB: Found Pseudo Instruction for Opcode "
- << MCII.getName(Opcode) << ", LMUL=" << I->getData()
- << ". Overriding original SchedClassID=" << SchedClassID
- << " with " << MCII.getName(RVV->Pseudo) << '\n');
- return MCII.get(RVV->Pseudo).getSchedClass();
- }
- }
-
- // Unknown Instrument kind
- LLVM_DEBUG(
- dbgs() << "RVCB: Did not use instrumentation to override Opcode.\n");
- return SchedClassID;
-}
-
-} // namespace mca
-} // namespace llvm
-
-using namespace llvm;
-using namespace mca;
-
-static InstrumentManager *
-createRISCVInstrumentManager(const MCSubtargetInfo &STI,
- const MCInstrInfo &MCII) {
- return new RISCVInstrumentManager(STI, MCII);
-}
-
-/// Extern function to initialize the targets for the RISCV backend
-extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTargetMCA() {
- TargetRegistry::RegisterInstrumentManager(getTheRISCV32Target(),
- createRISCVInstrumentManager);
- TargetRegistry::RegisterInstrumentManager(getTheRISCV64Target(),
- createRISCVInstrumentManager);
-}
+++ /dev/null
-//===-------------------- RISCVCustomBehaviour.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
-///
-/// This file defines the RISCVCustomBehaviour class which inherits from
-/// CustomBehaviour. This class is used by the tool llvm-mca to enforce
-/// target specific behaviour that is not expressed well enough in the
-/// scheduling model for mca to enforce it automatically.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_LIB_TARGET_RISCV_MCA_RISCVCUSTOMBEHAVIOUR_H
-#define LLVM_LIB_TARGET_RISCV_MCA_RISCVCUSTOMBEHAVIOUR_H
-
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/MC/MCInst.h"
-#include "llvm/MC/MCInstrDesc.h"
-#include "llvm/MC/MCInstrInfo.h"
-#include "llvm/MCA/CustomBehaviour.h"
-
-namespace llvm {
-namespace mca {
-
-class RISCVLMULInstrument : public Instrument {
-public:
- static const StringRef DESC_NAME;
- static bool isDataValid(StringRef Data);
-
- RISCVLMULInstrument(StringRef Data) : Instrument(DESC_NAME, Data) {}
-
- ~RISCVLMULInstrument() = default;
-
- uint8_t getLMUL() const;
-};
-
-class RISCVInstrumentManager : public InstrumentManager {
-public:
- RISCVInstrumentManager(const MCSubtargetInfo &STI, const MCInstrInfo &MCII)
- : InstrumentManager(STI, MCII) {}
-
- bool shouldIgnoreInstruments() const override { return false; }
- bool supportsInstrumentType(StringRef Type) const override;
-
- /// Create a Instrument for RISCV target
- SharedInstrument createInstrument(StringRef Desc, StringRef Data) override;
-
- /// Using the Instrument, returns a SchedClassID to use instead of
- /// the SchedClassID that belongs to the MCI or the original SchedClassID.
- unsigned
- getSchedClassID(const MCInstrInfo &MCII, const MCInst &MCI,
- const SmallVector<SharedInstrument> &IVec) const override;
-};
-
-} // namespace mca
-} // namespace llvm
-
-#endif
let PrimaryKeyEarlyOut = true;
}
-def RISCVVInversePseudosTable : GenericTable {
- let FilterClass = "RISCVVPseudo";
- let CppTypeName = "PseudoInfo";
- let Fields = [ "Pseudo", "BaseInstr", "VLMul" ];
- let PrimaryKey = [ "BaseInstr", "VLMul" ];
- let PrimaryKeyName = "getBaseInfo";
- let PrimaryKeyEarlyOut = true;
-}
-
def RISCVVIntrinsicsTable : GenericTable {
let FilterClass = "RISCVVIntrinsic";
let CppTypeName = "RISCVVIntrinsicInfo";
namespace llvm {
namespace mca {
+CodeRegions::CodeRegions(llvm::SourceMgr &S) : SM(S), FoundErrors(false) {
+ // Create a default region for the input code sequence.
+ Regions.emplace_back(std::make_unique<CodeRegion>("", SMLoc()));
+}
+
bool CodeRegion::isLocInRange(SMLoc Loc) const {
if (RangeEnd.isValid() && Loc.getPointer() > RangeEnd.getPointer())
return false;
return true;
}
-void CodeRegions::addInstruction(const MCInst &Instruction) {
- SMLoc Loc = Instruction.getLoc();
- for (UniqueCodeRegion &Region : Regions)
- if (Region->isLocInRange(Loc))
- Region->addInstruction(Instruction);
-}
-
-AnalysisRegions::AnalysisRegions(llvm::SourceMgr &S) : CodeRegions(S) {
- // Create a default region for the input code sequence.
- Regions.emplace_back(std::make_unique<CodeRegion>("", SMLoc()));
-}
-
-void AnalysisRegions::beginRegion(StringRef Description, SMLoc Loc) {
+void CodeRegions::beginRegion(StringRef Description, SMLoc Loc) {
if (ActiveRegions.empty()) {
// Remove the default region if there is at least one user defined region.
// By construction, only the default region has an invalid start location.
if (It != ActiveRegions.end()) {
const CodeRegion &R = *Regions[It->second];
if (Description.empty()) {
- SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
+ SM.PrintMessage(Loc, SourceMgr::DK_Error,
"found multiple overlapping anonymous regions");
- SM.PrintMessage(R.startLoc(), llvm::SourceMgr::DK_Note,
+ SM.PrintMessage(R.startLoc(), SourceMgr::DK_Note,
"Previous anonymous region was defined here");
FoundErrors = true;
return;
}
- SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
+ SM.PrintMessage(Loc, SourceMgr::DK_Error,
"overlapping regions cannot have the same name");
- SM.PrintMessage(R.startLoc(), llvm::SourceMgr::DK_Note,
+ SM.PrintMessage(R.startLoc(), SourceMgr::DK_Note,
"region " + Description + " was previously defined here");
FoundErrors = true;
return;
Regions.emplace_back(std::make_unique<CodeRegion>(Description, Loc));
}
-void AnalysisRegions::endRegion(StringRef Description, SMLoc Loc) {
+void CodeRegions::endRegion(StringRef Description, SMLoc Loc) {
if (Description.empty()) {
// Special case where there is only one user defined region,
// and this LLVM-MCA-END directive doesn't provide a region name.
}
FoundErrors = true;
- SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
+ SM.PrintMessage(Loc, SourceMgr::DK_Error,
"found an invalid region end directive");
if (!Description.empty()) {
- SM.PrintMessage(Loc, llvm::SourceMgr::DK_Note,
+ SM.PrintMessage(Loc, SourceMgr::DK_Note,
"unable to find an active region named " + Description);
} else {
- SM.PrintMessage(Loc, llvm::SourceMgr::DK_Note,
+ SM.PrintMessage(Loc, SourceMgr::DK_Note,
"unable to find an active anonymous region");
}
}
-InstrumentRegions::InstrumentRegions(llvm::SourceMgr &S) : CodeRegions(S) {}
-
-void InstrumentRegions::beginRegion(StringRef Description, SMLoc Loc,
- SharedInstrument I) {
- if (Description.empty()) {
- SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
- "anonymous instrumentation regions are not permitted");
- FoundErrors = true;
- return;
- }
-
- auto It = ActiveRegions.find(Description);
- if (It != ActiveRegions.end()) {
- const CodeRegion &R = *Regions[It->second];
- SM.PrintMessage(
- Loc, llvm::SourceMgr::DK_Error,
- "overlapping instrumentation regions cannot be of the same kind");
- SM.PrintMessage(R.startLoc(), llvm::SourceMgr::DK_Note,
- "instrumentation region " + Description +
- " was previously defined here");
- FoundErrors = true;
- return;
- }
-
- ActiveRegions[Description] = Regions.size();
- Regions.emplace_back(std::make_unique<InstrumentRegion>(Description, Loc, I));
-}
-
-void InstrumentRegions::endRegion(StringRef Description, SMLoc Loc) {
- auto It = ActiveRegions.find(Description);
- if (It != ActiveRegions.end()) {
- Regions[It->second]->setEndLocation(Loc);
- ActiveRegions.erase(It);
- return;
- }
-
- FoundErrors = true;
- SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
- "found an invalid instrumentation region end directive");
- if (!Description.empty()) {
- SM.PrintMessage(Loc, llvm::SourceMgr::DK_Note,
- "unable to find an active instrumentation region named " +
- Description);
- }
-}
-
-const SmallVector<SharedInstrument>
-InstrumentRegions::getActiveInstruments(SMLoc Loc) const {
- SmallVector<SharedInstrument, 2> AI;
- for (auto &R : Regions) {
- if (R->isLocInRange(Loc)) {
- InstrumentRegion *IR = static_cast<InstrumentRegion *>(R.get());
- AI.emplace_back(IR->getInstrument());
- }
- }
- return AI;
+void CodeRegions::addInstruction(const MCInst &Instruction) {
+ SMLoc Loc = Instruction.getLoc();
+ for (UniqueCodeRegion &Region : Regions)
+ if (Region->isLocInRange(Loc))
+ Region->addInstruction(Instruction);
}
} // namespace mca
//===----------------------------------------------------------------------===//
/// \file
///
-/// This file implements class CodeRegion and CodeRegions, InstrumentRegion,
-/// AnalysisRegions, and InstrumentRegions.
+/// This file implements class CodeRegion and CodeRegions.
///
/// A CodeRegion describes a region of assembly code guarded by special LLVM-MCA
/// comment directives.
/// description; internally, regions are described by a range of source
/// locations (SMLoc objects).
///
-/// An instruction (a MCInst) is added to a CodeRegion R only if its
-/// location is in range [R.RangeStart, R.RangeEnd].
-///
-/// A InstrumentRegion describes a region of assembly code guarded by
-/// special LLVM-MCA comment directives.
-///
-/// # LLVM-MCA-<INSTRUMENTATION_TYPE> <data>
-/// ... ## asm
-///
-/// where INSTRUMENTATION_TYPE is a type defined in llvm and expects to use
-/// data.
-///
-/// A comment starting with substring LLVM-MCA-<INSTRUMENTATION_TYPE>
-/// brings data into scope for llvm-mca to use in its analysis for
-/// all following instructions.
-///
-/// If the same INSTRUMENTATION_TYPE is found later in the instruction list,
-/// then the original InstrumentRegion will be automatically ended,
-/// and a new InstrumentRegion will begin.
-///
-/// If there are comments containing the different INSTRUMENTATION_TYPEs,
-/// then both data sets remain available. In contrast with a CodeRegion,
-/// an InstrumentRegion does not need a comment to end the region.
-//
-// An instruction (a MCInst) is added to an InstrumentRegion R only
-// if its location is in range [R.RangeStart, R.RangeEnd].
+/// An instruction (a MCInst) is added to a region R only if its location is in
+/// range [R.RangeStart, R.RangeEnd].
//
//===----------------------------------------------------------------------===//
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/MC/MCInst.h"
-#include "llvm/MCA/CustomBehaviour.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/SMLoc.h"
#include "llvm/Support/SourceMgr.h"
llvm::StringRef getDescription() const { return Description; }
};
-/// Alias AnalysisRegion with CodeRegion since CodeRegionGenerator
-/// is absract and AnalysisRegionGenerator operates on AnalysisRegions
-using AnalysisRegion = CodeRegion;
-
-/// A CodeRegion that contains instrumentation that can be used
-/// in analysis of the region.
-class InstrumentRegion : public CodeRegion {
- /// Instrument for this region.
- SharedInstrument Instrument;
-
-public:
- InstrumentRegion(llvm::StringRef Desc, llvm::SMLoc Start, SharedInstrument I)
- : CodeRegion(Desc, Start), Instrument(I) {}
-
-public:
- SharedInstrument getInstrument() const { return Instrument; }
-};
-
class CodeRegionParseError final : public Error {};
class CodeRegions {
- CodeRegions(const CodeRegions &) = delete;
- CodeRegions &operator=(const CodeRegions &) = delete;
-
-protected:
// A source manager. Used by the tool to generate meaningful warnings.
llvm::SourceMgr &SM;
llvm::StringMap<unsigned> ActiveRegions;
bool FoundErrors;
+ CodeRegions(const CodeRegions &) = delete;
+ CodeRegions &operator=(const CodeRegions &) = delete;
+
public:
- CodeRegions(llvm::SourceMgr &S) : SM(S), FoundErrors(false) {}
+ CodeRegions(llvm::SourceMgr &S);
typedef std::vector<UniqueCodeRegion>::iterator iterator;
typedef std::vector<UniqueCodeRegion>::const_iterator const_iterator;
const_iterator begin() const { return Regions.cbegin(); }
const_iterator end() const { return Regions.cend(); }
+ void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc);
+ void endRegion(llvm::StringRef Description, llvm::SMLoc Loc);
void addInstruction(const llvm::MCInst &Instruction);
llvm::SourceMgr &getSourceMgr() const { return SM; }
}
bool isValid() const { return !FoundErrors; }
-
- bool isRegionActive(llvm::StringRef Description) const {
- return ActiveRegions.find(Description) != ActiveRegions.end();
- }
-};
-
-struct AnalysisRegions : public CodeRegions {
- AnalysisRegions(llvm::SourceMgr &S);
-
- void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc);
- void endRegion(llvm::StringRef Description, llvm::SMLoc Loc);
-};
-
-struct InstrumentRegions : public CodeRegions {
- InstrumentRegions(llvm::SourceMgr &S);
-
- void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc,
- SharedInstrument Instrument);
- void endRegion(llvm::StringRef Description, llvm::SMLoc Loc);
-
- const SmallVector<SharedInstrument>
- getActiveInstruments(llvm::SMLoc Loc) const;
};
} // namespace mca
#include "CodeRegionGenerator.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/MC/MCParser/MCAsmLexer.h"
#include "llvm/MC/MCParser/MCTargetAsmParser.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCTargetOptions.h"
// This virtual dtor serves as the anchor for the CodeRegionGenerator class.
CodeRegionGenerator::~CodeRegionGenerator() {}
+// A comment consumer that parses strings. The only valid tokens are strings.
+class MCACommentConsumer : public AsmCommentConsumer {
+public:
+ CodeRegions &Regions;
+
+ MCACommentConsumer(CodeRegions &R) : Regions(R) {}
+ void HandleComment(SMLoc Loc, StringRef CommentText) override;
+};
+
// This class provides the callbacks that occur when parsing input assembly.
class MCStreamerWrapper final : public MCStreamer {
CodeRegions &Regions;
}
};
-Expected<const CodeRegions &> AsmCodeRegionGenerator::parseCodeRegions(
- const std::unique_ptr<MCInstPrinter> &IP) {
- MCTargetOptions Opts;
- Opts.PreserveAsmComments = false;
- CodeRegions &Regions = getRegions();
- MCStreamerWrapper Str(Ctx, Regions);
-
- // Need to initialize an MCTargetStreamer otherwise
- // certain asm directives will cause a segfault.
- // Using nulls() so that anything emitted by the MCTargetStreamer
- // doesn't show up in the llvm-mca output.
- raw_ostream &OSRef = nulls();
- formatted_raw_ostream FOSRef(OSRef);
- 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));
- MCAsmLexer &Lexer = Parser->getLexer();
- MCACommentConsumer *CCP = getCommentConsumer();
- Lexer.setCommentConsumer(CCP);
- // Enable support for MASM literal numbers (example: 05h, 101b).
- Lexer.setLexMasmIntegers(true);
-
- std::unique_ptr<MCTargetAsmParser> TAP(
- TheTarget.createMCAsmParser(STI, *Parser, MCII, Opts));
- if (!TAP)
- return make_error<StringError>(
- "This target does not support assembly parsing.",
- inconvertibleErrorCode());
- Parser->setTargetParser(*TAP);
- Parser->Run(false);
-
- if (CCP->hadErr())
- return make_error<StringError>("There was an error parsing comments.",
- inconvertibleErrorCode());
-
- // Set the assembler dialect from the input. llvm-mca will use this as the
- // default dialect when printing reports.
- AssemblerDialect = Parser->getAssemblerDialect();
- return Regions;
-}
-
-void AnalysisRegionCommentConsumer::HandleComment(SMLoc Loc,
- StringRef CommentText) {
+void MCACommentConsumer::HandleComment(SMLoc Loc, StringRef CommentText) {
// Skip empty comments.
StringRef Comment(CommentText);
if (Comment.empty())
Regions.beginRegion(Comment, Loc);
}
-void InstrumentRegionCommentConsumer::HandleComment(SMLoc Loc,
- StringRef CommentText) {
- // Skip empty comments.
- StringRef Comment(CommentText);
- if (Comment.empty())
- return;
-
- // Skip spaces and tabs.
- unsigned Position = Comment.find_first_not_of(" \t");
- if (Position >= Comment.size())
- // We reached the end of the comment. Bail out.
- return;
- Comment = Comment.drop_front(Position);
-
- // Bail out if not an MCA style comment
- if (!Comment.consume_front("LLVM-MCA-"))
- return;
-
- // Skip AnalysisRegion comments
- if (Comment.consume_front("BEGIN") || Comment.consume_front("END"))
- return;
+Expected<const CodeRegions &> AsmCodeRegionGenerator::parseCodeRegions(
+ const std::unique_ptr<MCInstPrinter> &IP) {
+ MCTargetOptions Opts;
+ Opts.PreserveAsmComments = false;
+ MCStreamerWrapper Str(Ctx, Regions);
- if (IM.shouldIgnoreInstruments())
- return;
+ // Need to initialize an MCTargetStreamer otherwise
+ // certain asm directives will cause a segfault.
+ // Using nulls() so that anything emitted by the MCTargetStreamer
+ // doesn't show up in the llvm-mca output.
+ raw_ostream &OSRef = nulls();
+ formatted_raw_ostream FOSRef(OSRef);
+ TheTarget.createAsmTargetStreamer(Str, FOSRef, IP.get(),
+ /*IsVerboseAsm=*/true);
- auto [InstrumentKind, Data] = Comment.split(" ");
-
- // An error if not of the form LLVM-MCA-TARGET-KIND
- if (!IM.supportsInstrumentType(InstrumentKind)) {
- if (InstrumentKind.empty())
- SM.PrintMessage(
- Loc, llvm::SourceMgr::DK_Error,
- "No instrumentation kind was provided in LLVM-MCA comment");
- else
- SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
- "Unknown instrumentation type in LLVM-MCA comment: " +
- InstrumentKind);
- FoundError = true;
- return;
- }
+ // Create a MCAsmParser and setup the lexer to recognize llvm-mca ASM
+ // comments.
+ std::unique_ptr<MCAsmParser> Parser(
+ createMCAsmParser(Regions.getSourceMgr(), Ctx, Str, MAI));
+ MCAsmLexer &Lexer = Parser->getLexer();
+ MCACommentConsumer CC(Regions);
+ Lexer.setCommentConsumer(&CC);
+ // Enable support for MASM literal numbers (example: 05h, 101b).
+ Lexer.setLexMasmIntegers(true);
- SharedInstrument I = IM.createInstrument(InstrumentKind, Data);
- if (!I) {
- if (Data.empty())
- SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
- "Failed to create " + InstrumentKind +
- " instrument with no data");
- else
- SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
- "Failed to create " + InstrumentKind +
- " instrument with data: " + Data);
- FoundError = true;
- return;
- }
+ std::unique_ptr<MCTargetAsmParser> TAP(
+ TheTarget.createMCAsmParser(STI, *Parser, MCII, Opts));
+ if (!TAP)
+ return make_error<StringError>(
+ "This target does not support assembly parsing.",
+ inconvertibleErrorCode());
+ Parser->setTargetParser(*TAP);
+ Parser->Run(false);
- // End InstrumentType region if one is open
- if (Regions.isRegionActive(InstrumentKind))
- Regions.endRegion(InstrumentKind, Loc);
- // Start new instrumentation region
- Regions.beginRegion(InstrumentKind, Loc, I);
+ // Set the assembler dialect from the input. llvm-mca will use this as the
+ // default dialect when printing reports.
+ AssemblerDialect = Parser->getAssemblerDialect();
+ return Regions;
}
} // namespace mca
#include "CodeRegion.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCParser/MCAsmLexer.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/TargetRegistry.h"
-#include "llvm/MCA/CustomBehaviour.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/SourceMgr.h"
#include <memory>
namespace llvm {
namespace mca {
-class MCACommentConsumer : public AsmCommentConsumer {
-protected:
- bool FoundError;
-
-public:
- MCACommentConsumer() : FoundError(false) {}
-
- bool hadErr() const { return FoundError; }
-};
-
-/// A comment consumer that parses strings. The only valid tokens are strings.
-class AnalysisRegionCommentConsumer : public MCACommentConsumer {
- AnalysisRegions &Regions;
-
-public:
- AnalysisRegionCommentConsumer(AnalysisRegions &R) : Regions(R) {}
-
- /// Parses a comment. It begins a new region if it is of the form
- /// LLVM-MCA-BEGIN. It ends a region if it is of the form LLVM-MCA-END.
- /// Regions can be optionally named if they are of the form
- /// LLVM-MCA-BEGIN <name> or LLVM-MCA-END <name>. Subregions are
- /// permitted, but a region that begins while another region is active
- /// must be ended before the outer region is ended. If thre is only one
- /// active region, LLVM-MCA-END does not need to provide a name.
- void HandleComment(SMLoc Loc, StringRef CommentText) override;
-};
-
-/// A comment consumer that parses strings to create InstrumentRegions.
-/// The only valid tokens are strings.
-class InstrumentRegionCommentConsumer : public MCACommentConsumer {
- llvm::SourceMgr &SM;
-
- InstrumentRegions &Regions;
-
- InstrumentManager &IM;
-
-public:
- InstrumentRegionCommentConsumer(llvm::SourceMgr &SM, InstrumentRegions &R,
- InstrumentManager &IM)
- : SM(SM), Regions(R), IM(IM) {}
-
- /// Parses a comment. It begins a new region if it is of the form
- /// LLVM-MCA-<INSTRUMENTATION_TYPE> <data> where INSTRUMENTATION_TYPE
- /// is a valid InstrumentKind. If there is already an active
- /// 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;
-};
-
-/// This abstract class is responsible for parsing the input given to
-/// the llvm-mca driver, and converting that into a CodeRegions instance.
+/// This class is responsible for parsing the input given to the llvm-mca
+/// driver, and converting that into a CodeRegions instance.
class CodeRegionGenerator {
protected:
+ CodeRegions Regions;
CodeRegionGenerator(const CodeRegionGenerator &) = delete;
CodeRegionGenerator &operator=(const CodeRegionGenerator &) = delete;
- virtual Expected<const CodeRegions &>
- parseCodeRegions(const std::unique_ptr<MCInstPrinter> &IP) = 0;
public:
- CodeRegionGenerator() {}
+ CodeRegionGenerator(llvm::SourceMgr &SM) : Regions(SM) {}
virtual ~CodeRegionGenerator();
+ virtual Expected<const CodeRegions &>
+ parseCodeRegions(const std::unique_ptr<MCInstPrinter> &IP) = 0;
};
-/// Abastract CodeRegionGenerator with AnalysisRegions member
-class AnalysisRegionGenerator : public virtual CodeRegionGenerator {
-protected:
- AnalysisRegions Regions;
-
-public:
- AnalysisRegionGenerator(llvm::SourceMgr &SM) : Regions(SM) {}
-
- virtual Expected<const AnalysisRegions &>
- parseAnalysisRegions(const std::unique_ptr<MCInstPrinter> &IP) = 0;
-};
-
-/// Abstract CodeRegionGenerator with InstrumentRegionsRegions member
-class InstrumentRegionGenerator : public virtual CodeRegionGenerator {
-protected:
- InstrumentRegions Regions;
-
-public:
- InstrumentRegionGenerator(llvm::SourceMgr &SM) : Regions(SM) {}
-
- virtual Expected<const InstrumentRegions &>
- parseInstrumentRegions(const std::unique_ptr<MCInstPrinter> &IP) = 0;
-};
-
-/// This abstract class is responsible for parsing input ASM and
-/// generating a CodeRegions instance.
-class AsmCodeRegionGenerator : public virtual CodeRegionGenerator {
+/// This class is responsible for parsing input ASM and generating
+/// a CodeRegions instance.
+class AsmCodeRegionGenerator final : public CodeRegionGenerator {
const Target &TheTarget;
MCContext &Ctx;
const MCAsmInfo &MAI;
unsigned AssemblerDialect; // This is set during parsing.
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) {}
-
- virtual MCACommentConsumer *getCommentConsumer() = 0;
- virtual CodeRegions &getRegions() = 0;
+ AsmCodeRegionGenerator(const Target &T, llvm::SourceMgr &SM, MCContext &C,
+ const MCAsmInfo &A, const MCSubtargetInfo &S,
+ const MCInstrInfo &I)
+ : CodeRegionGenerator(SM), TheTarget(T), Ctx(C), MAI(A), STI(S), MCII(I),
+ AssemblerDialect(0) {}
unsigned getAssemblerDialect() const { return AssemblerDialect; }
Expected<const CodeRegions &>
parseCodeRegions(const std::unique_ptr<MCInstPrinter> &IP) override;
};
-class AsmAnalysisRegionGenerator final : public AnalysisRegionGenerator,
- public AsmCodeRegionGenerator {
- AnalysisRegionCommentConsumer CC;
-
-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) {}
-
- MCACommentConsumer *getCommentConsumer() override { return &CC; };
- CodeRegions &getRegions() override { return Regions; };
-
- Expected<const AnalysisRegions &>
- parseAnalysisRegions(const std::unique_ptr<MCInstPrinter> &IP) override {
- Expected<const CodeRegions &> RegionsOrErr = parseCodeRegions(IP);
- if (!RegionsOrErr)
- return RegionsOrErr.takeError();
- else
- return static_cast<const AnalysisRegions &>(*RegionsOrErr);
- }
-};
-
-class AsmInstrumentRegionGenerator final : public InstrumentRegionGenerator,
- public AsmCodeRegionGenerator {
- InstrumentRegionCommentConsumer CC;
-
-public:
- AsmInstrumentRegionGenerator(const Target &T, llvm::SourceMgr &SM,
- MCContext &C, const MCAsmInfo &A,
- const MCSubtargetInfo &S, const MCInstrInfo &I,
- InstrumentManager &IM)
- : InstrumentRegionGenerator(SM), AsmCodeRegionGenerator(T, C, A, S, I),
- CC(SM, Regions, IM) {}
-
- MCACommentConsumer *getCommentConsumer() override { return &CC; };
- CodeRegions &getRegions() override { return Regions; };
-
- Expected<const InstrumentRegions &>
- parseInstrumentRegions(const std::unique_ptr<MCInstPrinter> &IP) override {
- Expected<const CodeRegions &> RegionsOrErr = parseCodeRegions(IP);
- if (!RegionsOrErr)
- return RegionsOrErr.takeError();
- else
- return static_cast<const InstrumentRegions &>(*RegionsOrErr);
- }
-};
-
} // namespace mca
} // namespace llvm
"Disable custom behaviour (use the default class which does nothing)."),
cl::cat(ViewOptions), cl::init(false));
-static cl::opt<bool> DisableInstrumentManager(
- "disable-im",
- cl::desc("Disable instrumentation manager (use the default class which "
- "ignores instruments.)."),
- cl::cat(ViewOptions), cl::init(false));
-
namespace {
const Target *getTarget(const char *ProgName) {
// Need to initialize an MCInstPrinter as it is
// required for initializing the MCTargetStreamer
- // which needs to happen within the CRG.parseAnalysisRegions() call below.
+ // which needs to happen within the CRG.parseCodeRegions() call below.
// Without an MCTargetStreamer, certain assembly directives can trigger a
// segfault. (For example, the .cv_fpo_proc directive on x86 will segfault if
// we don't initialize the MCTargetStreamer.)
}
// Parse the input and create CodeRegions that llvm-mca can analyze.
- mca::AsmAnalysisRegionGenerator CRG(*TheTarget, SrcMgr, Ctx, *MAI, *STI,
- *MCII);
- Expected<const mca::AnalysisRegions &> RegionsOrErr =
- CRG.parseAnalysisRegions(std::move(IPtemp));
+ mca::AsmCodeRegionGenerator CRG(*TheTarget, SrcMgr, Ctx, *MAI, *STI, *MCII);
+ Expected<const mca::CodeRegions &> RegionsOrErr =
+ CRG.parseCodeRegions(std::move(IPtemp));
if (!RegionsOrErr) {
if (auto Err =
handleErrors(RegionsOrErr.takeError(), [](const StringError &E) {
}
return 1;
}
- const mca::AnalysisRegions &Regions = *RegionsOrErr;
+ const mca::CodeRegions &Regions = *RegionsOrErr;
// Early exit if errors were found by the code region parsing logic.
if (!Regions.isValid())
return 1;
}
- std::unique_ptr<mca::InstrumentManager> IM;
- if (!DisableInstrumentManager) {
- IM = std::unique_ptr<mca::InstrumentManager>(
- TheTarget->createInstrumentManager(*STI, *MCII));
- }
- if (!IM) {
- // If the target doesn't have its own IM implemented (or the -disable-cb
- // flag is set) then we use the base class (which does nothing).
- IM = std::make_unique<mca::InstrumentManager>(*STI, *MCII);
- }
-
- // Parse the input and create InstrumentRegion that llvm-mca
- // can use to improve analysis.
- mca::AsmInstrumentRegionGenerator IRG(*TheTarget, SrcMgr, Ctx, *MAI, *STI,
- *MCII, *IM);
- Expected<const mca::InstrumentRegions &> InstrumentRegionsOrErr =
- IRG.parseInstrumentRegions(std::move(IPtemp));
- if (!InstrumentRegionsOrErr) {
- if (auto Err = handleErrors(InstrumentRegionsOrErr.takeError(),
- [](const StringError &E) {
- WithColor::error() << E.getMessage() << '\n';
- })) {
- // Default case.
- WithColor::error() << toString(std::move(Err)) << '\n';
- }
- return 1;
- }
- const mca::InstrumentRegions &InstrumentRegions = *InstrumentRegionsOrErr;
-
- // Early exit if errors were found by the instrumentation parsing logic.
- if (!InstrumentRegions.isValid())
- return 1;
-
// Now initialize the output file.
auto OF = getOutputStream();
if (std::error_code EC = OF.getError()) {
}
// Create an instruction builder.
- mca::InstrBuilder IB(*STI, *MCII, *MRI, MCIA.get(), *IM);
+ mca::InstrBuilder IB(*STI, *MCII, *MRI, MCIA.get());
// Create a context to control ownership of the pipeline hardware.
mca::Context MCA(*MRI, *STI);
assert(MAB && "Unable to create asm backend!");
json::Object JSONOutput;
- for (const std::unique_ptr<mca::AnalysisRegion> &Region : Regions) {
+ for (const std::unique_ptr<mca::CodeRegion> &Region : Regions) {
// Skip empty code regions.
if (Region->empty())
continue;
SmallVector<std::unique_ptr<mca::Instruction>> LoweredSequence;
for (const MCInst &MCI : Insts) {
- SMLoc Loc = MCI.getLoc();
- const SmallVector<mca::SharedInstrument> Instruments =
- InstrumentRegions.getActiveInstruments(Loc);
-
Expected<std::unique_ptr<mca::Instruction>> Inst =
- IB.createInstruction(MCI, Instruments);
+ IB.createInstruction(MCI);
if (!Inst) {
if (auto NewE = handleErrors(
Inst.takeError(),
const mca::PipelineOptions *PO) {
mca::Context MCA(*MRI, *STI);
- // Default InstrumentManager
- auto IM = std::make_unique<mca::InstrumentManager>(*STI, *MCII);
- mca::InstrBuilder IB(*STI, *MCII, *MRI, MCIA.get(), *IM);
+ mca::InstrBuilder IB(*STI, *MCII, *MRI, MCIA.get());
- const SmallVector<mca::SharedInstrument> Instruments;
SmallVector<std::unique_ptr<mca::Instruction>> LoweredInsts;
for (const auto &MCI : Insts) {
Expected<std::unique_ptr<mca::Instruction>> Inst =
- IB.createInstruction(MCI, Instruments);
+ IB.createInstruction(MCI);
if (!Inst) {
if (auto NewE =
handleErrors(Inst.takeError(),
PO.DispatchWidth);
P->addEventListener(SV.get());
- auto IM = std::make_unique<mca::InstrumentManager>(*STI, *MCII);
- mca::InstrBuilder IB(*STI, *MCII, *MRI, MCIA.get(), *IM);
+ mca::InstrBuilder IB(*STI, *MCII, *MRI, MCIA.get());
- const SmallVector<mca::SharedInstrument> Instruments;
// Tile size = 7
for (unsigned i = 0U, E = MCIs.size(); i < E;) {
for (unsigned TE = i + 7; i < TE && i < E; ++i) {
Expected<std::unique_ptr<mca::Instruction>> InstOrErr =
- IB.createInstruction(MCIs[i], Instruments);
+ IB.createInstruction(MCIs[i]);
ASSERT_TRUE(bool(InstOrErr));
ISM.addInst(std::move(InstOrErr.get()));
}
PO.DispatchWidth);
P->addEventListener(SV.get());
- // Default InstrumentManager
- auto IM = std::make_unique<mca::InstrumentManager>(*STI, *MCII);
-
- mca::InstrBuilder IB(*STI, *MCII, *MRI, MCIA.get(), *IM);
+ mca::InstrBuilder IB(*STI, *MCII, *MRI, MCIA.get());
IB.setInstRecycleCallback(GetRecycledInst);
- const SmallVector<mca::SharedInstrument> Instruments;
// Tile size = 7
for (unsigned i = 0U, E = MCIs.size(); i < E;) {
for (unsigned TE = i + 7; i < TE && i < E; ++i) {
Expected<std::unique_ptr<mca::Instruction>> InstOrErr =
- IB.createInstruction(MCIs[i], Instruments);
+ IB.createInstruction(MCIs[i]);
if (!InstOrErr) {
mca::Instruction *RecycledInst = nullptr;