Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

671 lines
24 KiB
C++
Raw Normal View History

//===-- llvm-mca.cpp - Machine Code Analyzer -------------------*- 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
//
//===----------------------------------------------------------------------===//
//
// This utility is a simple driver that allows static performance analysis on
// machine code similarly to how IACA (Intel Architecture Code Analyzer) works.
//
// llvm-mca [options] <file-name>
// -march <type>
// -mcpu <cpu>
// -o <file>
//
// The target defaults to the host target.
// The cpu defaults to the 'native' host cpu.
// The output defaults to standard output.
//
//===----------------------------------------------------------------------===//
[llvm-mca] Add the ability to mark regions of code for analysis (PR36875) This patch teaches llvm-mca how to parse code comments in search for special "markers" used to select regions of code. Example: # LLVM-MCA-BEGIN My Code Region .... # LLVM-MCA-END The MCAsmLexer now delegates to an object of class MCACommentParser (i.e. an AsmCommentConsumer) the parsing of code comments to search for begin/end code region markers. A comment starting with substring "LLVM-MCA-BEGIN" marks the beginning of a new region of code. A comment starting with substring "LLVM-MCA-END" marks the end of the last region. This implementation doesn't allow regions to overlap. Each region can have a optional description; internally, each region is identified by a range of source code locations (SMLoc). MCInst objects are added to a region R only if the source location for the MCInst is in the range of locations specified by R. By default, the tool allocates an implicit "Default" code region which contains every source location. See new tests llvm-mca-marker-*.s for a few examples. A new Backend object is created for every region. So, the analysis is conducted on every parsed code region. The final report is the union of the reports generated for every code region. Note that empty regions are skipped. Special "[#] Code Region - ..." strings are used in the report to mark the portion which is specific to a code region only. For example, see llvm-mca-markers-5.s. Differential Revision: https://reviews.llvm.org/D45433 llvm-svn: 329590
2018-04-09 16:39:52 +00:00
#include "CodeRegion.h"
#include "CodeRegionGenerator.h"
#include "PipelinePrinter.h"
#include "Views/BottleneckAnalysis.h"
#include "Views/DispatchStatistics.h"
#include "Views/InstructionInfoView.h"
#include "Views/RegisterFileStatistics.h"
#include "Views/ResourcePressureView.h"
#include "Views/RetireControlUnitStatistics.h"
#include "Views/SchedulerStatistics.h"
#include "Views/SummaryView.h"
#include "Views/TimelineView.h"
#ifdef HAS_AMDGPU
#include "lib/AMDGPU/AMDGPUCustomBehaviour.h"
#endif
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCTargetOptionsCommandFlags.h"
#include "llvm/MCA/CodeEmitter.h"
#include "llvm/MCA/Context.h"
#include "llvm/MCA/CustomBehaviour.h"
#include "llvm/MCA/InstrBuilder.h"
#include "llvm/MCA/Pipeline.h"
#include "llvm/MCA/Stages/EntryStage.h"
#include "llvm/MCA/Stages/InstructionTables.h"
#include "llvm/MCA/Support.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Support/WithColor.h"
using namespace llvm;
static mc::RegisterMCTargetOptionsFlags MOF;
static cl::OptionCategory ToolOptions("Tool Options");
static cl::OptionCategory ViewOptions("View Options");
static cl::opt<std::string> InputFilename(cl::Positional,
cl::desc("<input file>"),
cl::cat(ToolOptions), cl::init("-"));
static cl::opt<std::string> OutputFilename("o", cl::desc("Output filename"),
cl::init("-"), cl::cat(ToolOptions),
cl::value_desc("filename"));
static cl::opt<std::string>
ArchName("march",
cl::desc("Target architecture. "
"See -version for available targets"),
cl::cat(ToolOptions));
static cl::opt<std::string>
TripleName("mtriple",
cl::desc("Target triple. See -version for available targets"),
cl::cat(ToolOptions));
static cl::opt<std::string>
MCPU("mcpu",
cl::desc("Target a specific cpu type (-mcpu=help for details)"),
cl::value_desc("cpu-name"), cl::cat(ToolOptions), cl::init("native"));
static cl::opt<std::string>
MATTR("mattr",
cl::desc("Additional target features."),
cl::cat(ToolOptions));
static cl::opt<bool>
PrintJson("json",
cl::desc("Print the output in json format"),
cl::cat(ToolOptions), cl::init(false));
static cl::opt<int>
OutputAsmVariant("output-asm-variant",
cl::desc("Syntax variant to use for output printing"),
cl::cat(ToolOptions), cl::init(-1));
static cl::opt<bool>
PrintImmHex("print-imm-hex", cl::cat(ToolOptions), cl::init(false),
cl::desc("Prefer hex format when printing immediate values"));
static cl::opt<unsigned> Iterations("iterations",
cl::desc("Number of iterations to run"),
cl::cat(ToolOptions), cl::init(0));
static cl::opt<unsigned>
DispatchWidth("dispatch", cl::desc("Override the processor dispatch width"),
cl::cat(ToolOptions), cl::init(0));
static cl::opt<unsigned>
RegisterFileSize("register-file-size",
cl::desc("Maximum number of physical registers which can "
"be used for register mappings"),
cl::cat(ToolOptions), cl::init(0));
2019-03-29 12:15:37 +00:00
static cl::opt<unsigned>
MicroOpQueue("micro-op-queue-size", cl::Hidden,
cl::desc("Number of entries in the micro-op queue"),
cl::cat(ToolOptions), cl::init(0));
static cl::opt<unsigned>
DecoderThroughput("decoder-throughput", cl::Hidden,
cl::desc("Maximum throughput from the decoders "
"(instructions per cycle)"),
cl::cat(ToolOptions), cl::init(0));
static cl::opt<bool>
PrintRegisterFileStats("register-file-stats",
cl::desc("Print register file statistics"),
cl::cat(ViewOptions), cl::init(false));
static cl::opt<bool> PrintDispatchStats("dispatch-stats",
cl::desc("Print dispatch statistics"),
cl::cat(ViewOptions), cl::init(false));
static cl::opt<bool>
PrintSummaryView("summary-view", cl::Hidden,
cl::desc("Print summary view (enabled by default)"),
cl::cat(ViewOptions), cl::init(true));
static cl::opt<bool> PrintSchedulerStats("scheduler-stats",
cl::desc("Print scheduler statistics"),
cl::cat(ViewOptions), cl::init(false));
static cl::opt<bool>
PrintRetireStats("retire-stats",
cl::desc("Print retire control unit statistics"),
cl::cat(ViewOptions), cl::init(false));
static cl::opt<bool> PrintResourcePressureView(
"resource-pressure",
cl::desc("Print the resource pressure view (enabled by default)"),
cl::cat(ViewOptions), cl::init(true));
static cl::opt<bool> PrintTimelineView("timeline",
cl::desc("Print the timeline view"),
cl::cat(ViewOptions), cl::init(false));
static cl::opt<unsigned> TimelineMaxIterations(
"timeline-max-iterations",
cl::desc("Maximum number of iterations to print in timeline view"),
cl::cat(ViewOptions), cl::init(0));
static cl::opt<unsigned> TimelineMaxCycles(
"timeline-max-cycles",
cl::desc(
"Maximum number of cycles in the timeline view. Defaults to 80 cycles"),
cl::cat(ViewOptions), cl::init(80));
static cl::opt<bool>
AssumeNoAlias("noalias",
cl::desc("If set, assume that loads and stores do not alias"),
cl::cat(ToolOptions), cl::init(true));
static cl::opt<unsigned> LoadQueueSize("lqueue",
cl::desc("Size of the load queue"),
cl::cat(ToolOptions), cl::init(0));
static cl::opt<unsigned> StoreQueueSize("squeue",
cl::desc("Size of the store queue"),
cl::cat(ToolOptions), cl::init(0));
static cl::opt<bool>
PrintInstructionTables("instruction-tables",
cl::desc("Print instruction tables"),
cl::cat(ToolOptions), cl::init(false));
static cl::opt<bool> PrintInstructionInfoView(
"instruction-info",
cl::desc("Print the instruction info view (enabled by default)"),
cl::cat(ViewOptions), cl::init(true));
static cl::opt<bool> EnableAllStats("all-stats",
cl::desc("Print all hardware statistics"),
cl::cat(ViewOptions), cl::init(false));
static cl::opt<bool>
EnableAllViews("all-views",
cl::desc("Print all views including hardware statistics"),
cl::cat(ViewOptions), cl::init(false));
[MCA] Highlight kernel bottlenecks in the summary view. This patch adds a new flag named -bottleneck-analysis to print out information about throughput bottlenecks. MCA knows how to identify and classify dynamic dispatch stalls. However, it doesn't know how to analyze and highlight kernel bottlenecks. The goal of this patch is to teach MCA how to correlate increases in backend pressure to backend stalls (and therefore, the loss of throughput). From a Scheduler point of view, backend pressure is a function of the scheduler buffer usage (i.e. how the number of uOps in the scheduler buffers changes over time). Backend pressure increases (or decreases) when there is a mismatch between the number of opcodes dispatched, and the number of opcodes issued in the same cycle. Since buffer resources are limited, continuous increases in backend pressure would eventually leads to dispatch stalls. So, there is a strong correlation between dispatch stalls, and how backpressure changed over time. This patch teaches how to identify situations where backend pressure increases due to: - unavailable pipeline resources. - data dependencies. Data dependencies may delay execution of instructions and therefore increase the time that uOps have to spend in the scheduler buffers. That often translates to an increase in backend pressure which may eventually lead to a bottleneck. Contention on pipeline resources may also delay execution of instructions, and lead to a temporary increase in backend pressure. Internally, the Scheduler classifies instructions based on whether register / memory operands are available or not. An instruction is marked as "ready to execute" only if data dependencies are fully resolved. Every cycle, the Scheduler attempts to execute all instructions that are ready to execute. If an instruction cannot execute because of unavailable pipeline resources, then the Scheduler internally updates a BusyResourceUnits mask with the ID of each unavailable resource. ExecuteStage is responsible for tracking changes in backend pressure. If backend pressure increases during a cycle because of contention on pipeline resources, then ExecuteStage sends a "backend pressure" event to the listeners. That event would contain information about instructions delayed by resource pressure, as well as the BusyResourceUnits mask. Note that ExecuteStage also knows how to identify situations where backpressure increased because of delays introduced by data dependencies. The SummaryView observes "backend pressure" events and prints out a "bottleneck report". Example of bottleneck report: ``` Cycles with backend pressure increase [ 99.89% ] Throughput Bottlenecks: Resource Pressure [ 0.00% ] Data Dependencies: [ 99.89% ] - Register Dependencies [ 0.00% ] - Memory Dependencies [ 99.89% ] ``` A bottleneck report is printed out only if increases in backend pressure eventually caused backend stalls. About the time complexity: Time complexity is linear in the number of instructions in the Scheduler::PendingSet. The average slowdown tends to be in the range of ~5-6%. For memory intensive kernels, the slowdown can be significant if flag -noalias=false is specified. In the worst case scenario I have observed a slowdown of ~30% when flag -noalias=false was specified. We can definitely recover part of that slowdown if we optimize class LSUnit (by doing extra bookkeeping to speedup queries). For now, this new analysis is disabled by default, and it can be enabled via flag -bottleneck-analysis. Users of MCA as a library can enable the generation of pressure events through the constructor of ExecuteStage. This patch partially addresses https://bugs.llvm.org/show_bug.cgi?id=37494 Differential Revision: https://reviews.llvm.org/D58728 llvm-svn: 355308
2019-03-04 11:52:34 +00:00
static cl::opt<bool> EnableBottleneckAnalysis(
"bottleneck-analysis",
cl::desc("Enable bottleneck analysis (disabled by default)"),
cl::cat(ViewOptions), cl::init(false));
static cl::opt<bool> ShowEncoding(
"show-encoding",
cl::desc("Print encoding information in the instruction info view"),
cl::cat(ViewOptions), cl::init(false));
static cl::opt<bool> DisableCustomBehaviour(
"disable-cb",
cl::desc(
"Disable custom behaviour (use the default class which does nothing)."),
cl::cat(ViewOptions), cl::init(false));
namespace {
const Target *getTarget(const char *ProgName) {
if (TripleName.empty())
TripleName = Triple::normalize(sys::getDefaultTargetTriple());
Triple TheTriple(TripleName);
// Get the target specific parser.
std::string Error;
const Target *TheTarget =
TargetRegistry::lookupTarget(ArchName, TheTriple, Error);
if (!TheTarget) {
errs() << ProgName << ": " << Error;
return nullptr;
}
// Update TripleName with the updated triple from the target lookup.
TripleName = TheTriple.str();
// Return the found target.
return TheTarget;
}
ErrorOr<std::unique_ptr<ToolOutputFile>> getOutputStream() {
if (OutputFilename == "")
OutputFilename = "-";
std::error_code EC;
[SystemZ][z/OS][Windows] Add new OF_TextWithCRLF flag and use this flag instead of OF_Text Problem: On SystemZ we need to open text files in text mode. On Windows, files opened in text mode adds a CRLF '\r\n' which may not be desirable. Solution: This patch adds two new flags - OF_CRLF which indicates that CRLF translation is used. - OF_TextWithCRLF = OF_Text | OF_CRLF indicates that the file is text and uses CRLF translation. Developers should now use either the OF_Text or OF_TextWithCRLF for text files and OF_None for binary files. If the developer doesn't want carriage returns on Windows, they should use OF_Text, if they do want carriage returns on Windows, they should use OF_TextWithCRLF. So this is the behaviour per platform with my patch: z/OS: OF_None: open in binary mode OF_Text : open in text mode OF_TextWithCRLF: open in text mode Windows: OF_None: open file with no carriage return OF_Text: open file with no carriage return OF_TextWithCRLF: open file with carriage return The Major change is in llvm/lib/Support/Windows/Path.inc to only set text mode if the OF_CRLF is set. ``` if (Flags & OF_CRLF) CrtOpenFlags |= _O_TEXT; ``` These following files are the ones that still use OF_Text which I left unchanged. I modified all these except raw_ostream.cpp in recent patches so I know these were previously in Binary mode on Windows. ./llvm/lib/Support/raw_ostream.cpp ./llvm/lib/TableGen/Main.cpp ./llvm/tools/dsymutil/DwarfLinkerForBinary.cpp ./llvm/unittests/Support/Path.cpp ./clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp ./clang/lib/Frontend/CompilerInstance.cpp ./clang/lib/Driver/Driver.cpp ./clang/lib/Driver/ToolChains/Clang.cpp Reviewed By: MaskRay Differential Revision: https://reviews.llvm.org/D99426
2021-04-06 07:22:41 -04:00
auto Out = std::make_unique<ToolOutputFile>(OutputFilename, EC,
sys::fs::OF_TextWithCRLF);
if (!EC)
return std::move(Out);
return EC;
}
} // end of anonymous namespace
static void processOptionImpl(cl::opt<bool> &O, const cl::opt<bool> &Default) {
if (!O.getNumOccurrences() || O.getPosition() < Default.getPosition())
O = Default.getValue();
}
static void processViewOptions(bool IsOutOfOrder) {
if (!EnableAllViews.getNumOccurrences() &&
!EnableAllStats.getNumOccurrences())
return;
if (EnableAllViews.getNumOccurrences()) {
processOptionImpl(PrintSummaryView, EnableAllViews);
if (IsOutOfOrder)
processOptionImpl(EnableBottleneckAnalysis, EnableAllViews);
processOptionImpl(PrintResourcePressureView, EnableAllViews);
processOptionImpl(PrintTimelineView, EnableAllViews);
processOptionImpl(PrintInstructionInfoView, EnableAllViews);
}
const cl::opt<bool> &Default =
EnableAllViews.getPosition() < EnableAllStats.getPosition()
? EnableAllStats
: EnableAllViews;
processOptionImpl(PrintRegisterFileStats, Default);
processOptionImpl(PrintDispatchStats, Default);
processOptionImpl(PrintSchedulerStats, Default);
if (IsOutOfOrder)
processOptionImpl(PrintRetireStats, Default);
}
std::unique_ptr<mca::InstrPostProcess>
createInstrPostProcess(const Triple &TheTriple, const MCSubtargetInfo &STI,
const MCInstrInfo &MCII) {
// Might be a good idea to have a separate flag so that InstrPostProcess
// can be used with or without CustomBehaviour
if (DisableCustomBehaviour)
return std::make_unique<mca::InstrPostProcess>(STI, MCII);
#ifdef HAS_AMDGPU
if (TheTriple.isAMDGPU())
return std::make_unique<mca::AMDGPUInstrPostProcess>(STI, MCII);
#endif
return std::make_unique<mca::InstrPostProcess>(STI, MCII);
}
std::unique_ptr<mca::CustomBehaviour>
createCustomBehaviour(const Triple &TheTriple, const MCSubtargetInfo &STI,
const mca::SourceMgr &SrcMgr, const MCInstrInfo &MCII) {
// Build the appropriate CustomBehaviour object for the current target.
// The CustomBehaviour class should never depend on the source code,
// but it can depend on the list of mca::Instruction and any classes
// that can be built using just the target info. If you need extra
// information from the source code or the list of MCInst, consider
// adding that information to the mca::Instruction class and setting
// it during InstrBuilder::createInstruction().
if (DisableCustomBehaviour)
return std::make_unique<mca::CustomBehaviour>(STI, SrcMgr, MCII);
#ifdef HAS_AMDGPU
if (TheTriple.isAMDGPU())
return std::make_unique<mca::AMDGPUCustomBehaviour>(STI, SrcMgr, MCII);
#endif
return std::make_unique<mca::CustomBehaviour>(STI, SrcMgr, MCII);
}
// Returns true on success.
static bool runPipeline(mca::Pipeline &P) {
// Handle pipeline errors here.
Expected<unsigned> Cycles = P.run();
if (!Cycles) {
WithColor::error() << toString(Cycles.takeError());
return false;
}
return true;
}
int main(int argc, char **argv) {
InitLLVM X(argc, argv);
// Initialize targets and assembly parsers.
InitializeAllTargetInfos();
InitializeAllTargetMCs();
InitializeAllAsmParsers();
// Enable printing of available targets when flag --version is specified.
cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion);
cl::HideUnrelatedOptions({&ToolOptions, &ViewOptions});
// Parse flags and initialize target options.
cl::ParseCommandLineOptions(argc, argv,
"llvm machine code performance analyzer.\n");
// Get the target from the triple. If a triple is not specified, then select
// the default triple for the host. If the triple doesn't correspond to any
// registered target, then exit with an error message.
const char *ProgName = argv[0];
const Target *TheTarget = getTarget(ProgName);
if (!TheTarget)
return 1;
// GetTarget() may replaced TripleName with a default triple.
// For safety, reconstruct the Triple object.
Triple TheTriple(TripleName);
ErrorOr<std::unique_ptr<MemoryBuffer>> BufferPtr =
MemoryBuffer::getFileOrSTDIN(InputFilename);
if (std::error_code EC = BufferPtr.getError()) {
WithColor::error() << InputFilename << ": " << EC.message() << '\n';
return 1;
}
if (MCPU == "native")
MCPU = std::string(llvm::sys::getHostCPUName());
std::unique_ptr<MCSubtargetInfo> STI(
TheTarget->createMCSubtargetInfo(TripleName, MCPU, MATTR));
assert(STI && "Unable to create subtarget info!");
if (!STI->isCPUStringValid(MCPU))
return 1;
bool IsOutOfOrder = STI->getSchedModel().isOutOfOrder();
if (!PrintInstructionTables && !IsOutOfOrder) {
WithColor::warning() << "support for in-order CPU '" << MCPU
<< "' is experimental.\n";
}
if (!STI->getSchedModel().hasInstrSchedModel()) {
WithColor::error()
<< "unable to find instruction-level scheduling information for"
<< " target triple '" << TheTriple.normalize() << "' and cpu '" << MCPU
<< "'.\n";
if (STI->getSchedModel().InstrItineraries)
WithColor::note()
<< "cpu '" << MCPU << "' provides itineraries. However, "
<< "instruction itineraries are currently unsupported.\n";
return 1;
}
// Apply overrides to llvm-mca specific options.
processViewOptions(IsOutOfOrder);
std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TripleName));
assert(MRI && "Unable to create target register info!");
MCTargetOptions MCOptions = mc::InitMCTargetOptionsFromFlags();
std::unique_ptr<MCAsmInfo> MAI(
TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));
assert(MAI && "Unable to create target asm info!");
SourceMgr SrcMgr;
// Tell SrcMgr about this buffer, which is what the parser will pick up.
SrcMgr.AddNewSourceBuffer(std::move(*BufferPtr), SMLoc());
MCContext Ctx(TheTriple, MAI.get(), MRI.get(), STI.get(), &SrcMgr);
std::unique_ptr<MCObjectFileInfo> MOFI(
TheTarget->createMCObjectFileInfo(Ctx, /*PIC=*/false));
Ctx.setObjectFileInfo(MOFI.get());
std::unique_ptr<buffer_ostream> BOS;
std::unique_ptr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo());
assert(MCII && "Unable to create instruction info!");
std::unique_ptr<MCInstrAnalysis> MCIA(
TheTarget->createMCInstrAnalysis(MCII.get()));
[MCA] llvm-mca MCTargetStreamer segfault fix In order to create the code regions for llvm-mca to analyze, llvm-mca creates an AsmCodeRegionGenerator and calls AsmCodeRegionGenerator::parseCodeRegions(). Within this function, both an MCAsmParser and MCTargetAsmParser are created so that MCAsmParser::Run() can be used to create the code regions for us. These parser classes were created for llvm-mc so they are designed to emit code with an MCStreamer and MCTargetStreamer that are expected to be setup and passed into the MCAsmParser constructor. Because llvm-mca doesn’t want to emit any code, an MCStreamerWrapper class gets created instead and passed into the MCAsmParser constructor. This wrapper inherits from MCStreamer and overrides many of the emit methods to just do nothing. The exception is the emitInstruction() method which calls Regions.addInstruction(Inst). This works well and allows llvm-mca to utilize llvm-mc’s MCAsmParser to build our code regions, however there are a few directives which rely on the MCTargetStreamer. llvm-mc assumes that the MCStreamer that gets passed into the MCAsmParser’s constructor has a valid pointer to an MCTargetStreamer. Because llvm-mca doesn’t setup an MCTargetStreamer, when the parser encounters one of those directives, a segfault will occur. In x86, each one of these 7 directives will cause this segfault if they exist in the input assembly to llvm-mca: .cv_fpo_proc .cv_fpo_setframe .cv_fpo_pushreg .cv_fpo_stackalloc .cv_fpo_stackalign .cv_fpo_endprologue .cv_fpo_endproc I haven’t looked at other targets, but I wouldn’t be surprised if some of the other ones also have certain directives which could result in this same segfault. My proposed solution is to simply initialize an MCTargetStreamer after we initialize the MCStreamerWrapper. The MCTargetStreamer requires an ostream object, but we don’t actually want any of these directives to be emitted anywhere, so I use an ostream created with the nulls() function. Since this needs to happen after the MCStreamerWrapper has been initialized, it needs to happen within the AsmCodeRegionGenerator::parseCodeRegions() function. The MCTargetStreamer also needs an MCInstPrinter which is easiest to initialize within the main() function of llvm-mca. So this MCInstPrinter gets constructed within main() then passed into the parseCodeRegions() function as a parameter. (If you feel like it would be appropriate and possible to create the MCInstPrinter within the parseCodeRegions() function, then feel free to modify my solution. That would stop us from having to pass it into the function and would limit its scope / lifetime.) My solution stops the segfault from happening and still passes all of the current (expected) llvm-mca tests. I also added a new test for x86 that checks for this segfault on an input that includes one of the .cv_fpo directives (this test fails without my solution, but passes with it). As far as I can tell, all of the functions that I modified are only called from within llvm-mca so there shouldn’t be any worries about breaking other tools. Differential Revision: https://reviews.llvm.org/D102709
2021-05-19 10:29:41 +01:00
// Need to initialize an MCInstPrinter as it is
// required for initializing the MCTargetStreamer
// 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.)
unsigned IPtempOutputAsmVariant =
OutputAsmVariant == -1 ? 0 : OutputAsmVariant;
std::unique_ptr<MCInstPrinter> IPtemp(TheTarget->createMCInstPrinter(
Triple(TripleName), IPtempOutputAsmVariant, *MAI, *MCII, *MRI));
if (!IPtemp) {
WithColor::error()
<< "unable to create instruction printer for target triple '"
<< TheTriple.normalize() << "' with assembly variant "
<< IPtempOutputAsmVariant << ".\n";
return 1;
}
// Parse the input and create CodeRegions that llvm-mca can analyze.
mca::AsmCodeRegionGenerator CRG(*TheTarget, SrcMgr, Ctx, *MAI, *STI, *MCII);
[MCA] llvm-mca MCTargetStreamer segfault fix In order to create the code regions for llvm-mca to analyze, llvm-mca creates an AsmCodeRegionGenerator and calls AsmCodeRegionGenerator::parseCodeRegions(). Within this function, both an MCAsmParser and MCTargetAsmParser are created so that MCAsmParser::Run() can be used to create the code regions for us. These parser classes were created for llvm-mc so they are designed to emit code with an MCStreamer and MCTargetStreamer that are expected to be setup and passed into the MCAsmParser constructor. Because llvm-mca doesn’t want to emit any code, an MCStreamerWrapper class gets created instead and passed into the MCAsmParser constructor. This wrapper inherits from MCStreamer and overrides many of the emit methods to just do nothing. The exception is the emitInstruction() method which calls Regions.addInstruction(Inst). This works well and allows llvm-mca to utilize llvm-mc’s MCAsmParser to build our code regions, however there are a few directives which rely on the MCTargetStreamer. llvm-mc assumes that the MCStreamer that gets passed into the MCAsmParser’s constructor has a valid pointer to an MCTargetStreamer. Because llvm-mca doesn’t setup an MCTargetStreamer, when the parser encounters one of those directives, a segfault will occur. In x86, each one of these 7 directives will cause this segfault if they exist in the input assembly to llvm-mca: .cv_fpo_proc .cv_fpo_setframe .cv_fpo_pushreg .cv_fpo_stackalloc .cv_fpo_stackalign .cv_fpo_endprologue .cv_fpo_endproc I haven’t looked at other targets, but I wouldn’t be surprised if some of the other ones also have certain directives which could result in this same segfault. My proposed solution is to simply initialize an MCTargetStreamer after we initialize the MCStreamerWrapper. The MCTargetStreamer requires an ostream object, but we don’t actually want any of these directives to be emitted anywhere, so I use an ostream created with the nulls() function. Since this needs to happen after the MCStreamerWrapper has been initialized, it needs to happen within the AsmCodeRegionGenerator::parseCodeRegions() function. The MCTargetStreamer also needs an MCInstPrinter which is easiest to initialize within the main() function of llvm-mca. So this MCInstPrinter gets constructed within main() then passed into the parseCodeRegions() function as a parameter. (If you feel like it would be appropriate and possible to create the MCInstPrinter within the parseCodeRegions() function, then feel free to modify my solution. That would stop us from having to pass it into the function and would limit its scope / lifetime.) My solution stops the segfault from happening and still passes all of the current (expected) llvm-mca tests. I also added a new test for x86 that checks for this segfault on an input that includes one of the .cv_fpo directives (this test fails without my solution, but passes with it). As far as I can tell, all of the functions that I modified are only called from within llvm-mca so there shouldn’t be any worries about breaking other tools. Differential Revision: https://reviews.llvm.org/D102709
2021-05-19 10:29:41 +01:00
Expected<const mca::CodeRegions &> RegionsOrErr =
CRG.parseCodeRegions(std::move(IPtemp));
if (!RegionsOrErr) {
if (auto Err =
handleErrors(RegionsOrErr.takeError(), [](const StringError &E) {
WithColor::error() << E.getMessage() << '\n';
})) {
// Default case.
WithColor::error() << toString(std::move(Err)) << '\n';
}
return 1;
}
const mca::CodeRegions &Regions = *RegionsOrErr;
// Early exit if errors were found by the code region parsing logic.
if (!Regions.isValid())
return 1;
[llvm-mca] Add the ability to mark regions of code for analysis (PR36875) This patch teaches llvm-mca how to parse code comments in search for special "markers" used to select regions of code. Example: # LLVM-MCA-BEGIN My Code Region .... # LLVM-MCA-END The MCAsmLexer now delegates to an object of class MCACommentParser (i.e. an AsmCommentConsumer) the parsing of code comments to search for begin/end code region markers. A comment starting with substring "LLVM-MCA-BEGIN" marks the beginning of a new region of code. A comment starting with substring "LLVM-MCA-END" marks the end of the last region. This implementation doesn't allow regions to overlap. Each region can have a optional description; internally, each region is identified by a range of source code locations (SMLoc). MCInst objects are added to a region R only if the source location for the MCInst is in the range of locations specified by R. By default, the tool allocates an implicit "Default" code region which contains every source location. See new tests llvm-mca-marker-*.s for a few examples. A new Backend object is created for every region. So, the analysis is conducted on every parsed code region. The final report is the union of the reports generated for every code region. Note that empty regions are skipped. Special "[#] Code Region - ..." strings are used in the report to mark the portion which is specific to a code region only. For example, see llvm-mca-markers-5.s. Differential Revision: https://reviews.llvm.org/D45433 llvm-svn: 329590
2018-04-09 16:39:52 +00:00
if (Regions.empty()) {
WithColor::error() << "no assembly instructions found.\n";
return 1;
}
// Now initialize the output file.
auto OF = getOutputStream();
if (std::error_code EC = OF.getError()) {
WithColor::error() << EC.message() << '\n';
return 1;
}
unsigned AssemblerDialect = CRG.getAssemblerDialect();
if (OutputAsmVariant >= 0)
AssemblerDialect = static_cast<unsigned>(OutputAsmVariant);
std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter(
Triple(TripleName), AssemblerDialect, *MAI, *MCII, *MRI));
if (!IP) {
WithColor::error()
<< "unable to create instruction printer for target triple '"
<< TheTriple.normalize() << "' with assembly variant "
<< AssemblerDialect << ".\n";
return 1;
}
// Set the display preference for hex vs. decimal immediates.
IP->setPrintImmHex(PrintImmHex);
std::unique_ptr<ToolOutputFile> TOF = std::move(*OF);
const MCSchedModel &SM = STI->getSchedModel();
// Create an instruction builder.
mca::InstrBuilder IB(*STI, *MCII, *MRI, MCIA.get());
// Create a context to control ownership of the pipeline hardware.
mca::Context MCA(*MRI, *STI);
2019-03-29 12:15:37 +00:00
mca::PipelineOptions PO(MicroOpQueue, DecoderThroughput, DispatchWidth,
RegisterFileSize, LoadQueueSize, StoreQueueSize,
AssumeNoAlias, EnableBottleneckAnalysis);
[llvm-mca] Add the ability to mark regions of code for analysis (PR36875) This patch teaches llvm-mca how to parse code comments in search for special "markers" used to select regions of code. Example: # LLVM-MCA-BEGIN My Code Region .... # LLVM-MCA-END The MCAsmLexer now delegates to an object of class MCACommentParser (i.e. an AsmCommentConsumer) the parsing of code comments to search for begin/end code region markers. A comment starting with substring "LLVM-MCA-BEGIN" marks the beginning of a new region of code. A comment starting with substring "LLVM-MCA-END" marks the end of the last region. This implementation doesn't allow regions to overlap. Each region can have a optional description; internally, each region is identified by a range of source code locations (SMLoc). MCInst objects are added to a region R only if the source location for the MCInst is in the range of locations specified by R. By default, the tool allocates an implicit "Default" code region which contains every source location. See new tests llvm-mca-marker-*.s for a few examples. A new Backend object is created for every region. So, the analysis is conducted on every parsed code region. The final report is the union of the reports generated for every code region. Note that empty regions are skipped. Special "[#] Code Region - ..." strings are used in the report to mark the portion which is specific to a code region only. For example, see llvm-mca-markers-5.s. Differential Revision: https://reviews.llvm.org/D45433 llvm-svn: 329590
2018-04-09 16:39:52 +00:00
// Number each region in the sequence.
unsigned RegionIdx = 0;
std::unique_ptr<MCCodeEmitter> MCE(
TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx));
assert(MCE && "Unable to create code emitter!");
std::unique_ptr<MCAsmBackend> MAB(TheTarget->createMCAsmBackend(
*STI, *MRI, mc::InitMCTargetOptionsFromFlags()));
assert(MAB && "Unable to create asm backend!");
[llvm-mca] Add the ability to mark regions of code for analysis (PR36875) This patch teaches llvm-mca how to parse code comments in search for special "markers" used to select regions of code. Example: # LLVM-MCA-BEGIN My Code Region .... # LLVM-MCA-END The MCAsmLexer now delegates to an object of class MCACommentParser (i.e. an AsmCommentConsumer) the parsing of code comments to search for begin/end code region markers. A comment starting with substring "LLVM-MCA-BEGIN" marks the beginning of a new region of code. A comment starting with substring "LLVM-MCA-END" marks the end of the last region. This implementation doesn't allow regions to overlap. Each region can have a optional description; internally, each region is identified by a range of source code locations (SMLoc). MCInst objects are added to a region R only if the source location for the MCInst is in the range of locations specified by R. By default, the tool allocates an implicit "Default" code region which contains every source location. See new tests llvm-mca-marker-*.s for a few examples. A new Backend object is created for every region. So, the analysis is conducted on every parsed code region. The final report is the union of the reports generated for every code region. Note that empty regions are skipped. Special "[#] Code Region - ..." strings are used in the report to mark the portion which is specific to a code region only. For example, see llvm-mca-markers-5.s. Differential Revision: https://reviews.llvm.org/D45433 llvm-svn: 329590
2018-04-09 16:39:52 +00:00
for (const std::unique_ptr<mca::CodeRegion> &Region : Regions) {
// Skip empty code regions.
if (Region->empty())
continue;
// Don't print the header of this region if it is the default region, and
// it doesn't have an end location.
if (Region->startLoc().isValid() || Region->endLoc().isValid()) {
TOF->os() << "\n[" << RegionIdx++ << "] Code Region";
StringRef Desc = Region->getDescription();
if (!Desc.empty())
TOF->os() << " - " << Desc;
TOF->os() << "\n\n";
}
// Lower the MCInst sequence into an mca::Instruction sequence.
ArrayRef<MCInst> Insts = Region->getInstructions();
mca::CodeEmitter CE(*STI, *MAB, *MCE, Insts);
std::unique_ptr<mca::InstrPostProcess> IPP =
createInstrPostProcess(TheTriple, *STI, *MCII);
std::vector<std::unique_ptr<mca::Instruction>> LoweredSequence;
for (const MCInst &MCI : Insts) {
Expected<std::unique_ptr<mca::Instruction>> Inst =
IB.createInstruction(MCI);
if (!Inst) {
if (auto NewE = handleErrors(
Inst.takeError(),
[&IP, &STI](const mca::InstructionError<MCInst> &IE) {
std::string InstructionStr;
raw_string_ostream SS(InstructionStr);
WithColor::error() << IE.Message << '\n';
IP->printInst(&IE.Inst, 0, "", *STI, SS);
SS.flush();
WithColor::note()
<< "instruction: " << InstructionStr << '\n';
})) {
// Default case.
WithColor::error() << toString(std::move(NewE));
}
return 1;
}
IPP->postProcessInstruction(Inst.get(), MCI);
LoweredSequence.emplace_back(std::move(Inst.get()));
}
mca::SourceMgr S(LoweredSequence, PrintInstructionTables ? 1 : Iterations);
[llvm-mca] Add the ability to mark regions of code for analysis (PR36875) This patch teaches llvm-mca how to parse code comments in search for special "markers" used to select regions of code. Example: # LLVM-MCA-BEGIN My Code Region .... # LLVM-MCA-END The MCAsmLexer now delegates to an object of class MCACommentParser (i.e. an AsmCommentConsumer) the parsing of code comments to search for begin/end code region markers. A comment starting with substring "LLVM-MCA-BEGIN" marks the beginning of a new region of code. A comment starting with substring "LLVM-MCA-END" marks the end of the last region. This implementation doesn't allow regions to overlap. Each region can have a optional description; internally, each region is identified by a range of source code locations (SMLoc). MCInst objects are added to a region R only if the source location for the MCInst is in the range of locations specified by R. By default, the tool allocates an implicit "Default" code region which contains every source location. See new tests llvm-mca-marker-*.s for a few examples. A new Backend object is created for every region. So, the analysis is conducted on every parsed code region. The final report is the union of the reports generated for every code region. Note that empty regions are skipped. Special "[#] Code Region - ..." strings are used in the report to mark the portion which is specific to a code region only. For example, see llvm-mca-markers-5.s. Differential Revision: https://reviews.llvm.org/D45433 llvm-svn: 329590
2018-04-09 16:39:52 +00:00
if (PrintInstructionTables) {
// Create a pipeline, stages, and a printer.
auto P = std::make_unique<mca::Pipeline>();
P->appendStage(std::make_unique<mca::EntryStage>(S));
P->appendStage(std::make_unique<mca::InstructionTables>(SM));
mca::PipelinePrinter Printer(*P, mca::View::OK_READABLE);
[llvm-mca] Add the ability to mark regions of code for analysis (PR36875) This patch teaches llvm-mca how to parse code comments in search for special "markers" used to select regions of code. Example: # LLVM-MCA-BEGIN My Code Region .... # LLVM-MCA-END The MCAsmLexer now delegates to an object of class MCACommentParser (i.e. an AsmCommentConsumer) the parsing of code comments to search for begin/end code region markers. A comment starting with substring "LLVM-MCA-BEGIN" marks the beginning of a new region of code. A comment starting with substring "LLVM-MCA-END" marks the end of the last region. This implementation doesn't allow regions to overlap. Each region can have a optional description; internally, each region is identified by a range of source code locations (SMLoc). MCInst objects are added to a region R only if the source location for the MCInst is in the range of locations specified by R. By default, the tool allocates an implicit "Default" code region which contains every source location. See new tests llvm-mca-marker-*.s for a few examples. A new Backend object is created for every region. So, the analysis is conducted on every parsed code region. The final report is the union of the reports generated for every code region. Note that empty regions are skipped. Special "[#] Code Region - ..." strings are used in the report to mark the portion which is specific to a code region only. For example, see llvm-mca-markers-5.s. Differential Revision: https://reviews.llvm.org/D45433 llvm-svn: 329590
2018-04-09 16:39:52 +00:00
// Create the views for this pipeline, execute, and emit a report.
[llvm-mca] Add the ability to mark regions of code for analysis (PR36875) This patch teaches llvm-mca how to parse code comments in search for special "markers" used to select regions of code. Example: # LLVM-MCA-BEGIN My Code Region .... # LLVM-MCA-END The MCAsmLexer now delegates to an object of class MCACommentParser (i.e. an AsmCommentConsumer) the parsing of code comments to search for begin/end code region markers. A comment starting with substring "LLVM-MCA-BEGIN" marks the beginning of a new region of code. A comment starting with substring "LLVM-MCA-END" marks the end of the last region. This implementation doesn't allow regions to overlap. Each region can have a optional description; internally, each region is identified by a range of source code locations (SMLoc). MCInst objects are added to a region R only if the source location for the MCInst is in the range of locations specified by R. By default, the tool allocates an implicit "Default" code region which contains every source location. See new tests llvm-mca-marker-*.s for a few examples. A new Backend object is created for every region. So, the analysis is conducted on every parsed code region. The final report is the union of the reports generated for every code region. Note that empty regions are skipped. Special "[#] Code Region - ..." strings are used in the report to mark the portion which is specific to a code region only. For example, see llvm-mca-markers-5.s. Differential Revision: https://reviews.llvm.org/D45433 llvm-svn: 329590
2018-04-09 16:39:52 +00:00
if (PrintInstructionInfoView) {
Printer.addView(std::make_unique<mca::InstructionInfoView>(
*STI, *MCII, CE, ShowEncoding, Insts, *IP));
[llvm-mca] Add the ability to mark regions of code for analysis (PR36875) This patch teaches llvm-mca how to parse code comments in search for special "markers" used to select regions of code. Example: # LLVM-MCA-BEGIN My Code Region .... # LLVM-MCA-END The MCAsmLexer now delegates to an object of class MCACommentParser (i.e. an AsmCommentConsumer) the parsing of code comments to search for begin/end code region markers. A comment starting with substring "LLVM-MCA-BEGIN" marks the beginning of a new region of code. A comment starting with substring "LLVM-MCA-END" marks the end of the last region. This implementation doesn't allow regions to overlap. Each region can have a optional description; internally, each region is identified by a range of source code locations (SMLoc). MCInst objects are added to a region R only if the source location for the MCInst is in the range of locations specified by R. By default, the tool allocates an implicit "Default" code region which contains every source location. See new tests llvm-mca-marker-*.s for a few examples. A new Backend object is created for every region. So, the analysis is conducted on every parsed code region. The final report is the union of the reports generated for every code region. Note that empty regions are skipped. Special "[#] Code Region - ..." strings are used in the report to mark the portion which is specific to a code region only. For example, see llvm-mca-markers-5.s. Differential Revision: https://reviews.llvm.org/D45433 llvm-svn: 329590
2018-04-09 16:39:52 +00:00
}
Printer.addView(
std::make_unique<mca::ResourcePressureView>(*STI, *IP, Insts));
if (!runPipeline(*P))
return 1;
Printer.printReport(TOF->os());
[llvm-mca] Add the ability to mark regions of code for analysis (PR36875) This patch teaches llvm-mca how to parse code comments in search for special "markers" used to select regions of code. Example: # LLVM-MCA-BEGIN My Code Region .... # LLVM-MCA-END The MCAsmLexer now delegates to an object of class MCACommentParser (i.e. an AsmCommentConsumer) the parsing of code comments to search for begin/end code region markers. A comment starting with substring "LLVM-MCA-BEGIN" marks the beginning of a new region of code. A comment starting with substring "LLVM-MCA-END" marks the end of the last region. This implementation doesn't allow regions to overlap. Each region can have a optional description; internally, each region is identified by a range of source code locations (SMLoc). MCInst objects are added to a region R only if the source location for the MCInst is in the range of locations specified by R. By default, the tool allocates an implicit "Default" code region which contains every source location. See new tests llvm-mca-marker-*.s for a few examples. A new Backend object is created for every region. So, the analysis is conducted on every parsed code region. The final report is the union of the reports generated for every code region. Note that empty regions are skipped. Special "[#] Code Region - ..." strings are used in the report to mark the portion which is specific to a code region only. For example, see llvm-mca-markers-5.s. Differential Revision: https://reviews.llvm.org/D45433 llvm-svn: 329590
2018-04-09 16:39:52 +00:00
continue;
}
// Create the CustomBehaviour object for enforcing Target Specific
// behaviours and dependencies that aren't expressed well enough
// in the tablegen. CB cannot depend on the list of MCInst or
// the source code (but it can depend on the list of
// mca::Instruction or any objects that can be reconstructed
// from the target information).
std::unique_ptr<mca::CustomBehaviour> CB =
createCustomBehaviour(TheTriple, *STI, S, *MCII);
// Create a basic pipeline simulating an out-of-order backend.
auto P = MCA.createDefaultPipeline(PO, S, *CB);
mca::PipelinePrinter Printer(*P, PrintJson ? mca::View::OK_JSON
: mca::View::OK_READABLE);
// When we output JSON, we add a view that contains the instructions
// and CPU resource information.
if (PrintJson)
Printer.addView(
std::make_unique<mca::InstructionView>(*STI, *IP, Insts, MCPU));
if (PrintSummaryView)
Printer.addView(
std::make_unique<mca::SummaryView>(SM, Insts, DispatchWidth));
if (EnableBottleneckAnalysis) {
if (!IsOutOfOrder) {
WithColor::warning()
<< "bottleneck analysis is not supported for in-order CPU '" << MCPU
<< "'.\n";
}
Printer.addView(std::make_unique<mca::BottleneckAnalysis>(
*STI, *IP, Insts, S.getNumIterations()));
}
[llvm-mca] Add the ability to mark regions of code for analysis (PR36875) This patch teaches llvm-mca how to parse code comments in search for special "markers" used to select regions of code. Example: # LLVM-MCA-BEGIN My Code Region .... # LLVM-MCA-END The MCAsmLexer now delegates to an object of class MCACommentParser (i.e. an AsmCommentConsumer) the parsing of code comments to search for begin/end code region markers. A comment starting with substring "LLVM-MCA-BEGIN" marks the beginning of a new region of code. A comment starting with substring "LLVM-MCA-END" marks the end of the last region. This implementation doesn't allow regions to overlap. Each region can have a optional description; internally, each region is identified by a range of source code locations (SMLoc). MCInst objects are added to a region R only if the source location for the MCInst is in the range of locations specified by R. By default, the tool allocates an implicit "Default" code region which contains every source location. See new tests llvm-mca-marker-*.s for a few examples. A new Backend object is created for every region. So, the analysis is conducted on every parsed code region. The final report is the union of the reports generated for every code region. Note that empty regions are skipped. Special "[#] Code Region - ..." strings are used in the report to mark the portion which is specific to a code region only. For example, see llvm-mca-markers-5.s. Differential Revision: https://reviews.llvm.org/D45433 llvm-svn: 329590
2018-04-09 16:39:52 +00:00
if (PrintInstructionInfoView)
Printer.addView(std::make_unique<mca::InstructionInfoView>(
*STI, *MCII, CE, ShowEncoding, Insts, *IP));
if (PrintDispatchStats)
Printer.addView(std::make_unique<mca::DispatchStatistics>());
if (PrintSchedulerStats)
Printer.addView(std::make_unique<mca::SchedulerStatistics>(*STI));
if (PrintRetireStats)
Printer.addView(std::make_unique<mca::RetireControlUnitStatistics>(SM));
[llvm-mca] Add the ability to mark regions of code for analysis (PR36875) This patch teaches llvm-mca how to parse code comments in search for special "markers" used to select regions of code. Example: # LLVM-MCA-BEGIN My Code Region .... # LLVM-MCA-END The MCAsmLexer now delegates to an object of class MCACommentParser (i.e. an AsmCommentConsumer) the parsing of code comments to search for begin/end code region markers. A comment starting with substring "LLVM-MCA-BEGIN" marks the beginning of a new region of code. A comment starting with substring "LLVM-MCA-END" marks the end of the last region. This implementation doesn't allow regions to overlap. Each region can have a optional description; internally, each region is identified by a range of source code locations (SMLoc). MCInst objects are added to a region R only if the source location for the MCInst is in the range of locations specified by R. By default, the tool allocates an implicit "Default" code region which contains every source location. See new tests llvm-mca-marker-*.s for a few examples. A new Backend object is created for every region. So, the analysis is conducted on every parsed code region. The final report is the union of the reports generated for every code region. Note that empty regions are skipped. Special "[#] Code Region - ..." strings are used in the report to mark the portion which is specific to a code region only. For example, see llvm-mca-markers-5.s. Differential Revision: https://reviews.llvm.org/D45433 llvm-svn: 329590
2018-04-09 16:39:52 +00:00
if (PrintRegisterFileStats)
Printer.addView(std::make_unique<mca::RegisterFileStatistics>(*STI));
[llvm-mca] Add the ability to mark regions of code for analysis (PR36875) This patch teaches llvm-mca how to parse code comments in search for special "markers" used to select regions of code. Example: # LLVM-MCA-BEGIN My Code Region .... # LLVM-MCA-END The MCAsmLexer now delegates to an object of class MCACommentParser (i.e. an AsmCommentConsumer) the parsing of code comments to search for begin/end code region markers. A comment starting with substring "LLVM-MCA-BEGIN" marks the beginning of a new region of code. A comment starting with substring "LLVM-MCA-END" marks the end of the last region. This implementation doesn't allow regions to overlap. Each region can have a optional description; internally, each region is identified by a range of source code locations (SMLoc). MCInst objects are added to a region R only if the source location for the MCInst is in the range of locations specified by R. By default, the tool allocates an implicit "Default" code region which contains every source location. See new tests llvm-mca-marker-*.s for a few examples. A new Backend object is created for every region. So, the analysis is conducted on every parsed code region. The final report is the union of the reports generated for every code region. Note that empty regions are skipped. Special "[#] Code Region - ..." strings are used in the report to mark the portion which is specific to a code region only. For example, see llvm-mca-markers-5.s. Differential Revision: https://reviews.llvm.org/D45433 llvm-svn: 329590
2018-04-09 16:39:52 +00:00
if (PrintResourcePressureView)
Printer.addView(
std::make_unique<mca::ResourcePressureView>(*STI, *IP, Insts));
[llvm-mca] Add the ability to mark regions of code for analysis (PR36875) This patch teaches llvm-mca how to parse code comments in search for special "markers" used to select regions of code. Example: # LLVM-MCA-BEGIN My Code Region .... # LLVM-MCA-END The MCAsmLexer now delegates to an object of class MCACommentParser (i.e. an AsmCommentConsumer) the parsing of code comments to search for begin/end code region markers. A comment starting with substring "LLVM-MCA-BEGIN" marks the beginning of a new region of code. A comment starting with substring "LLVM-MCA-END" marks the end of the last region. This implementation doesn't allow regions to overlap. Each region can have a optional description; internally, each region is identified by a range of source code locations (SMLoc). MCInst objects are added to a region R only if the source location for the MCInst is in the range of locations specified by R. By default, the tool allocates an implicit "Default" code region which contains every source location. See new tests llvm-mca-marker-*.s for a few examples. A new Backend object is created for every region. So, the analysis is conducted on every parsed code region. The final report is the union of the reports generated for every code region. Note that empty regions are skipped. Special "[#] Code Region - ..." strings are used in the report to mark the portion which is specific to a code region only. For example, see llvm-mca-markers-5.s. Differential Revision: https://reviews.llvm.org/D45433 llvm-svn: 329590
2018-04-09 16:39:52 +00:00
if (PrintTimelineView) {
unsigned TimelineIterations =
TimelineMaxIterations ? TimelineMaxIterations : 10;
Printer.addView(std::make_unique<mca::TimelineView>(
*STI, *IP, Insts, std::min(TimelineIterations, S.getNumIterations()),
TimelineMaxCycles));
[llvm-mca] Add the ability to mark regions of code for analysis (PR36875) This patch teaches llvm-mca how to parse code comments in search for special "markers" used to select regions of code. Example: # LLVM-MCA-BEGIN My Code Region .... # LLVM-MCA-END The MCAsmLexer now delegates to an object of class MCACommentParser (i.e. an AsmCommentConsumer) the parsing of code comments to search for begin/end code region markers. A comment starting with substring "LLVM-MCA-BEGIN" marks the beginning of a new region of code. A comment starting with substring "LLVM-MCA-END" marks the end of the last region. This implementation doesn't allow regions to overlap. Each region can have a optional description; internally, each region is identified by a range of source code locations (SMLoc). MCInst objects are added to a region R only if the source location for the MCInst is in the range of locations specified by R. By default, the tool allocates an implicit "Default" code region which contains every source location. See new tests llvm-mca-marker-*.s for a few examples. A new Backend object is created for every region. So, the analysis is conducted on every parsed code region. The final report is the union of the reports generated for every code region. Note that empty regions are skipped. Special "[#] Code Region - ..." strings are used in the report to mark the portion which is specific to a code region only. For example, see llvm-mca-markers-5.s. Differential Revision: https://reviews.llvm.org/D45433 llvm-svn: 329590
2018-04-09 16:39:52 +00:00
}
if (!runPipeline(*P))
return 1;
[llvm-mca] Add the ability to mark regions of code for analysis (PR36875) This patch teaches llvm-mca how to parse code comments in search for special "markers" used to select regions of code. Example: # LLVM-MCA-BEGIN My Code Region .... # LLVM-MCA-END The MCAsmLexer now delegates to an object of class MCACommentParser (i.e. an AsmCommentConsumer) the parsing of code comments to search for begin/end code region markers. A comment starting with substring "LLVM-MCA-BEGIN" marks the beginning of a new region of code. A comment starting with substring "LLVM-MCA-END" marks the end of the last region. This implementation doesn't allow regions to overlap. Each region can have a optional description; internally, each region is identified by a range of source code locations (SMLoc). MCInst objects are added to a region R only if the source location for the MCInst is in the range of locations specified by R. By default, the tool allocates an implicit "Default" code region which contains every source location. See new tests llvm-mca-marker-*.s for a few examples. A new Backend object is created for every region. So, the analysis is conducted on every parsed code region. The final report is the union of the reports generated for every code region. Note that empty regions are skipped. Special "[#] Code Region - ..." strings are used in the report to mark the portion which is specific to a code region only. For example, see llvm-mca-markers-5.s. Differential Revision: https://reviews.llvm.org/D45433 llvm-svn: 329590
2018-04-09 16:39:52 +00:00
Printer.printReport(TOF->os());
// Clear the InstrBuilder internal state in preparation for another round.
IB.clear();
}
TOF->keep();
return 0;
}