diff --git a/llvm/docs/CommandGuide/llvm-mca.rst b/llvm/docs/CommandGuide/llvm-mca.rst --- a/llvm/docs/CommandGuide/llvm-mca.rst +++ b/llvm/docs/CommandGuide/llvm-mca.rst @@ -997,7 +997,7 @@ purpose or the instruction's behaviour is quite complex). The CustomBehaviour class can be used in these cases to enforce proper instruction modeling (often by customizing data dependencies and detecting -hazards that :program:`llvm-ma` has no way of knowing about). +hazards that :program:`llvm-mca` has no way of knowing about). :program:`llvm-mca` comes with one generic and multiple target specific CustomBehaviour classes. The generic class will be used if the ``-disable-cb`` @@ -1017,3 +1017,30 @@ already have one, refer to an existing implementation to see how to set it up. The classes are implemented within the target specific backend (for example `/llvm/lib/Target/AMDGPU/MCA/`) so that they can access backend symbols. + +Custom Views +"""""""""""""""""""""""""""""""""""" +:program:`llvm-mca` comes with several Views such as the Timeline View and +Summary View. These Views are generic and can work with most (if not all) +targets. If you wish to add a new View to :program:`llvm-mca` and it does not +require any backend functionality that is not already exposed through MC layer +classes (MCSubtargetInfo, MCInstrInfo, etc.), please add it to the +`/tools/llvm-mca/View/` directory. However, if your new View is target specific +AND requires unexposed backend symbols or functionality, you can define it in +the `/lib/Target//MCA/` directory. + +To enable this target specific View, you will have to use this target's +CustomBehaviour class to override the `CustomBehaviour::getViews()` methods. +There are 3 variations of these methods based on where you want your View to +appear in the output: `getStartViews()`, `getPostInstrInfoViews()`, and +`getEndViews()`. These methods returns a vector of Views so you will want to +return a vector containing all of the target specific Views for the target in +question. + +Because these target specific (and backend dependent) Views require the +`CustomBehaviour::getViews()` variants, these Views will not be enabled if +the `-disable-cb` flag is used. + +Enabling these custom Views does not affect the non-custom (generic) Views. +Continue to use the usual command line arguments to enable / disable those +Views. 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 @@ -22,6 +22,7 @@ #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MCA/SourceMgr.h" +#include "llvm/MCA/View.h" namespace llvm { namespace mca { @@ -65,19 +66,43 @@ virtual ~CustomBehaviour(); - // Before the llvm-mca pipeline dispatches an instruction, it first checks - // for any register or resource dependencies / hazards. If it doesn't find - // any, this method will be invoked to determine if there are any custom - // hazards that the instruction needs to wait for. - // The return value of this method is the number of cycles that the - // instruction needs to wait for. - // It's safe to underestimate the number of cycles to wait for since these - // checks will be invoked again before the intruction gets dispatched. - // However, it's not safe (accurate) to overestimate the number of cycles - // to wait for since the instruction will wait for AT LEAST that number of - // cycles before attempting to be dispatched again. + /// Before the llvm-mca pipeline dispatches an instruction, it first checks + /// for any register or resource dependencies / hazards. If it doesn't find + /// any, this method will be invoked to determine if there are any custom + /// hazards that the instruction needs to wait for. + /// The return value of this method is the number of cycles that the + /// instruction needs to wait for. + /// It's safe to underestimate the number of cycles to wait for since these + /// checks will be invoked again before the intruction gets dispatched. + /// However, it's not safe (accurate) to overestimate the number of cycles + /// to wait for since the instruction will wait for AT LEAST that number of + /// cycles before attempting to be dispatched again. virtual unsigned checkCustomHazard(ArrayRef IssuedInst, const InstRef &IR); + + // Functions that target CBs can override to return a list of + // target specific Views that need to live within /lib/Target/ so that + // they can benefit from the target CB or from backend functionality that is + // not already exposed through MC-layer classes. Keep in mind that how this + // function is used is that the function is called within llvm-mca.cpp and + // then each unique_ptr is passed into the PipelinePrinter::addView() + // function. This function will then std::move the View into its own vector of + // Views. So any CB that overrides this function needs to make sure that they + // are not relying on the current address or reference of the View + // unique_ptrs. If you do need the CB and View to be able to communicate with + // each other, consider giving the View a reference or pointer to the CB when + // the View is constructed. Then the View can query the CB for information + // when it needs it. + /// Return a vector of Views that will be added before all other Views. + virtual std::vector> + getStartViews(llvm::MCInstPrinter &IP, llvm::ArrayRef Insts); + /// Return a vector of Views that will be added after the InstructionInfoView. + virtual std::vector> + getPostInstrInfoViews(llvm::MCInstPrinter &IP, + llvm::ArrayRef Insts); + /// Return a vector of Views that will be added after all other Views. + virtual std::vector> + getEndViews(llvm::MCInstPrinter &IP, llvm::ArrayRef Insts); }; } // namespace mca diff --git a/llvm/tools/llvm-mca/Views/View.h b/llvm/include/llvm/MCA/View.h rename from llvm/tools/llvm-mca/Views/View.h rename to llvm/include/llvm/MCA/View.h --- a/llvm/tools/llvm-mca/Views/View.h +++ b/llvm/include/llvm/MCA/View.h @@ -12,8 +12,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_TOOLS_LLVM_MCA_VIEW_H -#define LLVM_TOOLS_LLVM_MCA_VIEW_H +#ifndef LLVM_MCA_VIEW_H +#define LLVM_MCA_VIEW_H #include "llvm/MC/MCInstPrinter.h" #include "llvm/MCA/HWEventListener.h" diff --git a/llvm/lib/MCA/CMakeLists.txt b/llvm/lib/MCA/CMakeLists.txt --- a/llvm/lib/MCA/CMakeLists.txt +++ b/llvm/lib/MCA/CMakeLists.txt @@ -21,6 +21,7 @@ Stages/RetireStage.cpp Stages/Stage.cpp Support.cpp + View.cpp ADDITIONAL_HEADER_DIRS ${LLVM_MAIN_INCLUDE_DIR}/llvm/MCA 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 @@ -24,5 +24,23 @@ return 0; } +std::vector> +CustomBehaviour::getStartViews(llvm::MCInstPrinter &IP, + llvm::ArrayRef Insts) { + return std::vector>(); +} + +std::vector> +CustomBehaviour::getPostInstrInfoViews(llvm::MCInstPrinter &IP, + llvm::ArrayRef Insts) { + return std::vector>(); +} + +std::vector> +CustomBehaviour::getEndViews(llvm::MCInstPrinter &IP, + llvm::ArrayRef Insts) { + return std::vector>(); +} + } // namespace mca } // namespace llvm diff --git a/llvm/tools/llvm-mca/Views/View.cpp b/llvm/lib/MCA/View.cpp rename from llvm/tools/llvm-mca/Views/View.cpp rename to llvm/lib/MCA/View.cpp --- a/llvm/tools/llvm-mca/Views/View.cpp +++ b/llvm/lib/MCA/View.cpp @@ -11,7 +11,7 @@ /// //===----------------------------------------------------------------------===// -#include "Views/View.h" +#include "llvm/MCA/View.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCSubtargetInfo.h" diff --git a/llvm/tools/llvm-mca/CMakeLists.txt b/llvm/tools/llvm-mca/CMakeLists.txt --- a/llvm/tools/llvm-mca/CMakeLists.txt +++ b/llvm/tools/llvm-mca/CMakeLists.txt @@ -27,7 +27,6 @@ Views/SchedulerStatistics.cpp Views/SummaryView.cpp Views/TimelineView.cpp - Views/View.cpp ) set(LLVM_MCA_SOURCE_DIR ${CURRENT_SOURCE_DIR}) diff --git a/llvm/tools/llvm-mca/PipelinePrinter.h b/llvm/tools/llvm-mca/PipelinePrinter.h --- a/llvm/tools/llvm-mca/PipelinePrinter.h +++ b/llvm/tools/llvm-mca/PipelinePrinter.h @@ -16,11 +16,11 @@ #ifndef LLVM_TOOLS_LLVM_MCA_PIPELINEPRINTER_H #define LLVM_TOOLS_LLVM_MCA_PIPELINEPRINTER_H -#include "Views/View.h" #include "llvm/ADT/SmallVector.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MCA/Context.h" #include "llvm/MCA/Pipeline.h" +#include "llvm/MCA/View.h" #include "llvm/Support/raw_ostream.h" #define DEBUG_TYPE "llvm-mca" diff --git a/llvm/tools/llvm-mca/PipelinePrinter.cpp b/llvm/tools/llvm-mca/PipelinePrinter.cpp --- a/llvm/tools/llvm-mca/PipelinePrinter.cpp +++ b/llvm/tools/llvm-mca/PipelinePrinter.cpp @@ -14,7 +14,6 @@ #include "PipelinePrinter.h" #include "CodeRegion.h" #include "Views/InstructionView.h" -#include "Views/View.h" namespace llvm { namespace mca { diff --git a/llvm/tools/llvm-mca/Views/DispatchStatistics.h b/llvm/tools/llvm-mca/Views/DispatchStatistics.h --- a/llvm/tools/llvm-mca/Views/DispatchStatistics.h +++ b/llvm/tools/llvm-mca/Views/DispatchStatistics.h @@ -33,9 +33,9 @@ #ifndef LLVM_TOOLS_LLVM_MCA_DISPATCHVIEW_H #define LLVM_TOOLS_LLVM_MCA_DISPATCHVIEW_H -#include "Views/View.h" #include "llvm/ADT/SmallVector.h" #include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/MCA/View.h" #include namespace llvm { diff --git a/llvm/tools/llvm-mca/Views/InstructionView.h b/llvm/tools/llvm-mca/Views/InstructionView.h --- a/llvm/tools/llvm-mca/Views/InstructionView.h +++ b/llvm/tools/llvm-mca/Views/InstructionView.h @@ -15,7 +15,7 @@ #ifndef LLVM_TOOLS_LLVM_MCA_INSTRUCTIONVIEW_H #define LLVM_TOOLS_LLVM_MCA_INSTRUCTIONVIEW_H -#include "Views/View.h" +#include "llvm/MCA/View.h" #include "llvm/Support/JSON.h" #include "llvm/Support/raw_ostream.h" diff --git a/llvm/tools/llvm-mca/Views/RegisterFileStatistics.h b/llvm/tools/llvm-mca/Views/RegisterFileStatistics.h --- a/llvm/tools/llvm-mca/Views/RegisterFileStatistics.h +++ b/llvm/tools/llvm-mca/Views/RegisterFileStatistics.h @@ -35,9 +35,9 @@ #ifndef LLVM_TOOLS_LLVM_MCA_REGISTERFILESTATISTICS_H #define LLVM_TOOLS_LLVM_MCA_REGISTERFILESTATISTICS_H -#include "Views/View.h" #include "llvm/ADT/SmallVector.h" #include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/MCA/View.h" namespace llvm { namespace mca { diff --git a/llvm/tools/llvm-mca/Views/RetireControlUnitStatistics.h b/llvm/tools/llvm-mca/Views/RetireControlUnitStatistics.h --- a/llvm/tools/llvm-mca/Views/RetireControlUnitStatistics.h +++ b/llvm/tools/llvm-mca/Views/RetireControlUnitStatistics.h @@ -28,8 +28,8 @@ #ifndef LLVM_TOOLS_LLVM_MCA_RETIRECONTROLUNITSTATISTICS_H #define LLVM_TOOLS_LLVM_MCA_RETIRECONTROLUNITSTATISTICS_H -#include "Views/View.h" #include "llvm/MC/MCSchedule.h" +#include "llvm/MCA/View.h" #include namespace llvm { diff --git a/llvm/tools/llvm-mca/Views/SchedulerStatistics.h b/llvm/tools/llvm-mca/Views/SchedulerStatistics.h --- a/llvm/tools/llvm-mca/Views/SchedulerStatistics.h +++ b/llvm/tools/llvm-mca/Views/SchedulerStatistics.h @@ -36,9 +36,9 @@ #ifndef LLVM_TOOLS_LLVM_MCA_SCHEDULERSTATISTICS_H #define LLVM_TOOLS_LLVM_MCA_SCHEDULERSTATISTICS_H -#include "Views/View.h" #include "llvm/ADT/SmallVector.h" #include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/MCA/View.h" #include namespace llvm { diff --git a/llvm/tools/llvm-mca/Views/SummaryView.h b/llvm/tools/llvm-mca/Views/SummaryView.h --- a/llvm/tools/llvm-mca/Views/SummaryView.h +++ b/llvm/tools/llvm-mca/Views/SummaryView.h @@ -28,9 +28,9 @@ #ifndef LLVM_TOOLS_LLVM_MCA_SUMMARYVIEW_H #define LLVM_TOOLS_LLVM_MCA_SUMMARYVIEW_H -#include "Views/View.h" #include "llvm/ADT/DenseMap.h" #include "llvm/MC/MCSchedule.h" +#include "llvm/MCA/View.h" #include "llvm/Support/raw_ostream.h" namespace llvm { diff --git a/llvm/tools/llvm-mca/llvm-mca.cpp b/llvm/tools/llvm-mca/llvm-mca.cpp --- a/llvm/tools/llvm-mca/llvm-mca.cpp +++ b/llvm/tools/llvm-mca/llvm-mca.cpp @@ -591,6 +591,21 @@ mca::PipelinePrinter Printer(*P, *Region, RegionIdx, *STI, PO); + // Targets can define their own custom Views that exist within their + // /lib/Target/ directory so that the View can utilize their CustomBehaviour + // or other backend symbols / functionality that are not already exposed + // through one of the MC-layer classes. These Views will be initialized + // using the CustomBehaviour::getViews() variants. + // If a target makes a custom View that does not depend on their target + // CB or their backend, they should put the View within + // /tools/llvm-mca/Views/ instead. + if (!DisableCustomBehaviour) { + std::vector> CBViews = + CB->getStartViews(*IP, Insts); + for (auto &CBView : CBViews) + Printer.addView(std::move(CBView)); + } + // When we output JSON, we add a view that contains the instructions // and CPU resource information. if (PrintJson) { @@ -616,6 +631,16 @@ Printer.addView(std::make_unique( *STI, *MCII, CE, ShowEncoding, Insts, *IP)); + // Fetch custom Views that are to be placed after the InstructionInfoView. + // Refer to the comment paired with the CB->getStartViews(*IP, Insts); line + // for more info. + if (!DisableCustomBehaviour) { + std::vector> CBViews = + CB->getPostInstrInfoViews(*IP, Insts); + for (auto &CBView : CBViews) + Printer.addView(std::move(CBView)); + } + if (PrintDispatchStats) Printer.addView(std::make_unique()); @@ -640,6 +665,16 @@ TimelineMaxCycles)); } + // Fetch custom Views that are to be placed after all other Views. + // Refer to the comment paired with the CB->getStartViews(*IP, Insts); line + // for more info. + if (!DisableCustomBehaviour) { + std::vector> CBViews = + CB->getEndViews(*IP, Insts); + for (auto &CBView : CBViews) + Printer.addView(std::move(CBView)); + } + if (!runPipeline(*P)) return 1;