10b57cec5SDimitry Andric //===--------------------- BottleneckAnalysis.h -----------------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric /// \file 90b57cec5SDimitry Andric /// 100b57cec5SDimitry Andric /// This file implements the bottleneck analysis view. 110b57cec5SDimitry Andric /// 120b57cec5SDimitry Andric /// This view internally observes backend pressure increase events in order to 130b57cec5SDimitry Andric /// identify problematic data dependencies and processor resource interferences. 140b57cec5SDimitry Andric /// 150b57cec5SDimitry Andric /// Example of bottleneck analysis report for a dot-product on X86 btver2: 160b57cec5SDimitry Andric /// 170b57cec5SDimitry Andric /// Cycles with backend pressure increase [ 40.76% ] 180b57cec5SDimitry Andric /// Throughput Bottlenecks: 190b57cec5SDimitry Andric /// Resource Pressure [ 39.34% ] 200b57cec5SDimitry Andric /// - JFPA [ 39.34% ] 210b57cec5SDimitry Andric /// - JFPU0 [ 39.34% ] 220b57cec5SDimitry Andric /// Data Dependencies: [ 1.42% ] 230b57cec5SDimitry Andric /// - Register Dependencies [ 1.42% ] 240b57cec5SDimitry Andric /// - Memory Dependencies [ 0.00% ] 250b57cec5SDimitry Andric /// 260b57cec5SDimitry Andric /// According to the example, backend pressure increased during the 40.76% of 270b57cec5SDimitry Andric /// the simulated cycles. In particular, the major cause of backend pressure 280b57cec5SDimitry Andric /// increases was the contention on floating point adder JFPA accessible from 290b57cec5SDimitry Andric /// pipeline resource JFPU0. 300b57cec5SDimitry Andric /// 310b57cec5SDimitry Andric /// At the end of each cycle, if pressure on the simulated out-of-order buffers 320b57cec5SDimitry Andric /// has increased, a backend pressure event is reported. 330b57cec5SDimitry Andric /// In particular, this occurs when there is a delta between the number of uOps 340b57cec5SDimitry Andric /// dispatched and the number of uOps issued to the underlying pipelines. 350b57cec5SDimitry Andric /// 36fe6060f1SDimitry Andric /// The bottleneck analysis view is also responsible for identifying and 37fe6060f1SDimitry Andric /// printing the most "critical" sequence of dependent instructions according to 38fe6060f1SDimitry Andric /// the simulated run. 390b57cec5SDimitry Andric /// 400b57cec5SDimitry Andric /// Below is the critical sequence computed for the dot-product example on 410b57cec5SDimitry Andric /// btver2: 420b57cec5SDimitry Andric /// 430b57cec5SDimitry Andric /// Instruction Dependency Information 440b57cec5SDimitry Andric /// +----< 2. vhaddps %xmm3, %xmm3, %xmm4 450b57cec5SDimitry Andric /// | 460b57cec5SDimitry Andric /// | < loop carried > 470b57cec5SDimitry Andric /// | 480b57cec5SDimitry Andric /// | 0. vmulps %xmm0, %xmm0, %xmm2 490b57cec5SDimitry Andric /// +----> 1. vhaddps %xmm2, %xmm2, %xmm3 ## RESOURCE interference: JFPA [ probability: 73% ] 500b57cec5SDimitry Andric /// +----> 2. vhaddps %xmm3, %xmm3, %xmm4 ## REGISTER dependency: %xmm3 510b57cec5SDimitry Andric /// | 520b57cec5SDimitry Andric /// | < loop carried > 530b57cec5SDimitry Andric /// | 540b57cec5SDimitry Andric /// +----> 1. vhaddps %xmm2, %xmm2, %xmm3 ## RESOURCE interference: JFPA [ probability: 73% ] 550b57cec5SDimitry Andric /// 560b57cec5SDimitry Andric /// 570b57cec5SDimitry Andric /// The algorithm that computes the critical sequence is very similar to a 580b57cec5SDimitry Andric /// critical path analysis. 590b57cec5SDimitry Andric /// 600b57cec5SDimitry Andric /// A dependency graph is used internally to track dependencies between nodes. 610b57cec5SDimitry Andric /// Nodes of the graph represent instructions from the input assembly sequence, 620b57cec5SDimitry Andric /// and edges of the graph represent data dependencies or processor resource 630b57cec5SDimitry Andric /// interferences. 640b57cec5SDimitry Andric /// 65fe6060f1SDimitry Andric /// Edges are dynamically 'discovered' by observing instruction state 66fe6060f1SDimitry Andric /// transitions and backend pressure increase events. Edges are internally 67fe6060f1SDimitry Andric /// ranked based on their "criticality". A dependency is considered to be 68fe6060f1SDimitry Andric /// critical if it takes a long time to execute, and if it contributes to 69fe6060f1SDimitry Andric /// backend pressure increases. Criticality is internally measured in terms of 70fe6060f1SDimitry Andric /// cycles; it is computed for every edge in the graph as a function of the edge 71fe6060f1SDimitry Andric /// latency and the number of backend pressure increase cycles contributed by 72fe6060f1SDimitry Andric /// that edge. 730b57cec5SDimitry Andric /// 740b57cec5SDimitry Andric /// At the end of simulation, costs are propagated to nodes through the edges of 750b57cec5SDimitry Andric /// the graph, and the most expensive path connecting the root-set (a 760b57cec5SDimitry Andric /// set of nodes with no predecessors) to a leaf node is reported as critical 770b57cec5SDimitry Andric /// sequence. 780b57cec5SDimitry Andric // 790b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 800b57cec5SDimitry Andric 810b57cec5SDimitry Andric #ifndef LLVM_TOOLS_LLVM_MCA_BOTTLENECK_ANALYSIS_H 820b57cec5SDimitry Andric #define LLVM_TOOLS_LLVM_MCA_BOTTLENECK_ANALYSIS_H 830b57cec5SDimitry Andric 84e8d8bef9SDimitry Andric #include "Views/InstructionView.h" 850b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h" 860b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 870b57cec5SDimitry Andric #include "llvm/MC/MCInstPrinter.h" 880b57cec5SDimitry Andric #include "llvm/MC/MCSchedule.h" 890b57cec5SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h" 90e8d8bef9SDimitry Andric #include "llvm/Support/FormattedStream.h" 910b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric namespace llvm { 940b57cec5SDimitry Andric namespace mca { 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric class PressureTracker { 970b57cec5SDimitry Andric const MCSchedModel &SM; 980b57cec5SDimitry Andric 990b57cec5SDimitry Andric // Resource pressure distribution. There is an element for every processor 1000b57cec5SDimitry Andric // resource declared by the scheduling model. Quantities are number of cycles. 1010b57cec5SDimitry Andric SmallVector<unsigned, 4> ResourcePressureDistribution; 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric // Each processor resource is associated with a so-called processor resource 1040b57cec5SDimitry Andric // mask. This vector allows to correlate processor resource IDs with processor 1050b57cec5SDimitry Andric // resource masks. There is exactly one element per each processor resource 1060b57cec5SDimitry Andric // declared by the scheduling model. 1070b57cec5SDimitry Andric SmallVector<uint64_t, 4> ProcResID2Mask; 1080b57cec5SDimitry Andric 1090b57cec5SDimitry Andric // Maps processor resource state indices (returned by calls to 1100b57cec5SDimitry Andric // `getResourceStateIndex(Mask)` to processor resource identifiers. 1110b57cec5SDimitry Andric SmallVector<unsigned, 4> ResIdx2ProcResID; 1120b57cec5SDimitry Andric 1130b57cec5SDimitry Andric // Maps Processor Resource identifiers to ResourceUsers indices. 1140b57cec5SDimitry Andric SmallVector<unsigned, 4> ProcResID2ResourceUsersIndex; 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andric // Identifies the last user of a processor resource unit. 1170b57cec5SDimitry Andric // This vector is updated on every instruction issued event. 1180b57cec5SDimitry Andric // There is one entry for every processor resource unit declared by the 1190b57cec5SDimitry Andric // processor model. An all_ones value is treated like an invalid instruction 1200b57cec5SDimitry Andric // identifier. 1210b57cec5SDimitry Andric using User = std::pair<unsigned, unsigned>; 1220b57cec5SDimitry Andric SmallVector<User, 4> ResourceUsers; 1230b57cec5SDimitry Andric 1240b57cec5SDimitry Andric struct InstructionPressureInfo { 1250b57cec5SDimitry Andric unsigned RegisterPressureCycles; 1260b57cec5SDimitry Andric unsigned MemoryPressureCycles; 1270b57cec5SDimitry Andric unsigned ResourcePressureCycles; 1280b57cec5SDimitry Andric }; 1290b57cec5SDimitry Andric DenseMap<unsigned, InstructionPressureInfo> IPI; 1300b57cec5SDimitry Andric 1310b57cec5SDimitry Andric void updateResourcePressureDistribution(uint64_t CumulativeMask); 1320b57cec5SDimitry Andric getResourceUser(unsigned ProcResID,unsigned UnitID)1330b57cec5SDimitry Andric User getResourceUser(unsigned ProcResID, unsigned UnitID) const { 1340b57cec5SDimitry Andric unsigned Index = ProcResID2ResourceUsersIndex[ProcResID]; 1350b57cec5SDimitry Andric return ResourceUsers[Index + UnitID]; 1360b57cec5SDimitry Andric } 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric public: 1390b57cec5SDimitry Andric PressureTracker(const MCSchedModel &Model); 1400b57cec5SDimitry Andric getResourcePressureDistribution()1410b57cec5SDimitry Andric ArrayRef<unsigned> getResourcePressureDistribution() const { 1420b57cec5SDimitry Andric return ResourcePressureDistribution; 1430b57cec5SDimitry Andric } 1440b57cec5SDimitry Andric 1450b57cec5SDimitry Andric void getResourceUsers(uint64_t ResourceMask, 1460b57cec5SDimitry Andric SmallVectorImpl<User> &Users) const; 1470b57cec5SDimitry Andric getRegisterPressureCycles(unsigned IID)1480b57cec5SDimitry Andric unsigned getRegisterPressureCycles(unsigned IID) const { 149*06c3fb27SDimitry Andric assert(IPI.contains(IID) && "Instruction is not tracked!"); 1500b57cec5SDimitry Andric const InstructionPressureInfo &Info = IPI.find(IID)->second; 1510b57cec5SDimitry Andric return Info.RegisterPressureCycles; 1520b57cec5SDimitry Andric } 1530b57cec5SDimitry Andric getMemoryPressureCycles(unsigned IID)1540b57cec5SDimitry Andric unsigned getMemoryPressureCycles(unsigned IID) const { 155*06c3fb27SDimitry Andric assert(IPI.contains(IID) && "Instruction is not tracked!"); 1560b57cec5SDimitry Andric const InstructionPressureInfo &Info = IPI.find(IID)->second; 1570b57cec5SDimitry Andric return Info.MemoryPressureCycles; 1580b57cec5SDimitry Andric } 1590b57cec5SDimitry Andric getResourcePressureCycles(unsigned IID)1600b57cec5SDimitry Andric unsigned getResourcePressureCycles(unsigned IID) const { 161*06c3fb27SDimitry Andric assert(IPI.contains(IID) && "Instruction is not tracked!"); 1620b57cec5SDimitry Andric const InstructionPressureInfo &Info = IPI.find(IID)->second; 1630b57cec5SDimitry Andric return Info.ResourcePressureCycles; 1640b57cec5SDimitry Andric } 1650b57cec5SDimitry Andric resolveResourceName(uint64_t ResourceMask)1660b57cec5SDimitry Andric const char *resolveResourceName(uint64_t ResourceMask) const { 1670b57cec5SDimitry Andric unsigned Index = getResourceStateIndex(ResourceMask); 1680b57cec5SDimitry Andric unsigned ProcResID = ResIdx2ProcResID[Index]; 1690b57cec5SDimitry Andric const MCProcResourceDesc &PRDesc = *SM.getProcResource(ProcResID); 1700b57cec5SDimitry Andric return PRDesc.Name; 1710b57cec5SDimitry Andric } 1720b57cec5SDimitry Andric 1730b57cec5SDimitry Andric void onInstructionDispatched(unsigned IID); 1740b57cec5SDimitry Andric void onInstructionExecuted(unsigned IID); 1750b57cec5SDimitry Andric 1760b57cec5SDimitry Andric void handlePressureEvent(const HWPressureEvent &Event); 1770b57cec5SDimitry Andric void handleInstructionIssuedEvent(const HWInstructionIssuedEvent &Event); 1780b57cec5SDimitry Andric }; 1790b57cec5SDimitry Andric 1800b57cec5SDimitry Andric // A dependency edge. 1810b57cec5SDimitry Andric struct DependencyEdge { 1820b57cec5SDimitry Andric enum DependencyType { DT_INVALID, DT_REGISTER, DT_MEMORY, DT_RESOURCE }; 1830b57cec5SDimitry Andric 1840b57cec5SDimitry Andric // Dependency edge descriptor. 1850b57cec5SDimitry Andric // 1860b57cec5SDimitry Andric // It specifies the dependency type, as well as the edge cost in cycles. 1870b57cec5SDimitry Andric struct Dependency { 1880b57cec5SDimitry Andric DependencyType Type; 1890b57cec5SDimitry Andric uint64_t ResourceOrRegID; 1900b57cec5SDimitry Andric uint64_t Cost; 1910b57cec5SDimitry Andric }; 1920b57cec5SDimitry Andric Dependency Dep; 1930b57cec5SDimitry Andric 1940b57cec5SDimitry Andric unsigned FromIID; 1950b57cec5SDimitry Andric unsigned ToIID; 1960b57cec5SDimitry Andric 1970b57cec5SDimitry Andric // Used by the bottleneck analysis to compute the interference 1980b57cec5SDimitry Andric // probability for processor resources. 1990b57cec5SDimitry Andric unsigned Frequency; 2000b57cec5SDimitry Andric }; 2010b57cec5SDimitry Andric 2020b57cec5SDimitry Andric // A dependency graph used by the bottleneck analysis to describe data 2030b57cec5SDimitry Andric // dependencies and processor resource interferences between instructions. 2040b57cec5SDimitry Andric // 2050b57cec5SDimitry Andric // There is a node (an instance of struct DGNode) for every instruction in the 2060b57cec5SDimitry Andric // input assembly sequence. Edges of the graph represent dependencies between 2070b57cec5SDimitry Andric // instructions. 2080b57cec5SDimitry Andric // 2090b57cec5SDimitry Andric // Each edge of the graph is associated with a cost value which is used 2100b57cec5SDimitry Andric // internally to rank dependency based on their impact on the runtime 2110b57cec5SDimitry Andric // performance (see field DependencyEdge::Dependency::Cost). In general, the 2120b57cec5SDimitry Andric // higher the cost of an edge, the higher the impact on performance. 2130b57cec5SDimitry Andric // 2140b57cec5SDimitry Andric // The cost of a dependency is a function of both the latency and the number of 2150b57cec5SDimitry Andric // cycles where the dependency has been seen as critical (i.e. contributing to 2160b57cec5SDimitry Andric // back-pressure increases). 2170b57cec5SDimitry Andric // 2180b57cec5SDimitry Andric // Loop carried dependencies are carefully expanded by the bottleneck analysis 2190b57cec5SDimitry Andric // to guarantee that the graph stays acyclic. To this end, extra nodes are 2200b57cec5SDimitry Andric // pre-allocated at construction time to describe instructions from "past and 221fe6060f1SDimitry Andric // future" iterations. The graph is kept acyclic mainly because it simplifies 222fe6060f1SDimitry Andric // the complexity of the algorithm that computes the critical sequence. 2230b57cec5SDimitry Andric class DependencyGraph { 2240b57cec5SDimitry Andric struct DGNode { 2250b57cec5SDimitry Andric unsigned NumPredecessors; 2260b57cec5SDimitry Andric unsigned NumVisitedPredecessors; 2270b57cec5SDimitry Andric uint64_t Cost; 2280b57cec5SDimitry Andric unsigned Depth; 2290b57cec5SDimitry Andric 2300b57cec5SDimitry Andric DependencyEdge CriticalPredecessor; 2310b57cec5SDimitry Andric SmallVector<DependencyEdge, 8> OutgoingEdges; 2320b57cec5SDimitry Andric }; 2330b57cec5SDimitry Andric SmallVector<DGNode, 16> Nodes; 2340b57cec5SDimitry Andric 2350b57cec5SDimitry Andric DependencyGraph(const DependencyGraph &) = delete; 2360b57cec5SDimitry Andric DependencyGraph &operator=(const DependencyGraph &) = delete; 2370b57cec5SDimitry Andric 2380b57cec5SDimitry Andric void addDependency(unsigned From, unsigned To, 2390b57cec5SDimitry Andric DependencyEdge::Dependency &&DE); 2400b57cec5SDimitry Andric 2418bcb0991SDimitry Andric void pruneEdges(unsigned Iterations); 2420b57cec5SDimitry Andric void initializeRootSet(SmallVectorImpl<unsigned> &RootSet) const; 243fe6060f1SDimitry Andric void propagateThroughEdges(SmallVectorImpl<unsigned> &RootSet, 244fe6060f1SDimitry Andric unsigned Iterations); 2450b57cec5SDimitry Andric 2460b57cec5SDimitry Andric #ifndef NDEBUG 2470b57cec5SDimitry Andric void dumpDependencyEdge(raw_ostream &OS, const DependencyEdge &DE, 2480b57cec5SDimitry Andric MCInstPrinter &MCIP) const; 2490b57cec5SDimitry Andric #endif 2500b57cec5SDimitry Andric 2510b57cec5SDimitry Andric public: DependencyGraph(unsigned Size)2520b57cec5SDimitry Andric DependencyGraph(unsigned Size) : Nodes(Size) {} 2530b57cec5SDimitry Andric addRegisterDep(unsigned From,unsigned To,unsigned RegID,unsigned Cost)2540b57cec5SDimitry Andric void addRegisterDep(unsigned From, unsigned To, unsigned RegID, 2550b57cec5SDimitry Andric unsigned Cost) { 2560b57cec5SDimitry Andric addDependency(From, To, {DependencyEdge::DT_REGISTER, RegID, Cost}); 2570b57cec5SDimitry Andric } 2580b57cec5SDimitry Andric addMemoryDep(unsigned From,unsigned To,unsigned Cost)2590b57cec5SDimitry Andric void addMemoryDep(unsigned From, unsigned To, unsigned Cost) { 2600b57cec5SDimitry Andric addDependency(From, To, {DependencyEdge::DT_MEMORY, /* unused */ 0, Cost}); 2610b57cec5SDimitry Andric } 2620b57cec5SDimitry Andric addResourceDep(unsigned From,unsigned To,uint64_t Mask,unsigned Cost)2630b57cec5SDimitry Andric void addResourceDep(unsigned From, unsigned To, uint64_t Mask, 2640b57cec5SDimitry Andric unsigned Cost) { 2650b57cec5SDimitry Andric addDependency(From, To, {DependencyEdge::DT_RESOURCE, Mask, Cost}); 2660b57cec5SDimitry Andric } 2670b57cec5SDimitry Andric 2680b57cec5SDimitry Andric // Called by the bottleneck analysis at the end of simulation to propagate 2690b57cec5SDimitry Andric // costs through the edges of the graph, and compute a critical path. finalizeGraph(unsigned Iterations)2708bcb0991SDimitry Andric void finalizeGraph(unsigned Iterations) { 2710b57cec5SDimitry Andric SmallVector<unsigned, 16> RootSet; 2728bcb0991SDimitry Andric pruneEdges(Iterations); 2730b57cec5SDimitry Andric initializeRootSet(RootSet); 2748bcb0991SDimitry Andric propagateThroughEdges(RootSet, Iterations); 2750b57cec5SDimitry Andric } 2760b57cec5SDimitry Andric 2770b57cec5SDimitry Andric // Returns a sequence of edges representing the critical sequence based on the 2780b57cec5SDimitry Andric // simulated run. It assumes that the graph has already been finalized (i.e. 2790b57cec5SDimitry Andric // method `finalizeGraph()` has already been called on this graph). 2800b57cec5SDimitry Andric void getCriticalSequence(SmallVectorImpl<const DependencyEdge *> &Seq) const; 2810b57cec5SDimitry Andric 2820b57cec5SDimitry Andric #ifndef NDEBUG 2830b57cec5SDimitry Andric void dump(raw_ostream &OS, MCInstPrinter &MCIP) const; 2840b57cec5SDimitry Andric #endif 2850b57cec5SDimitry Andric }; 2860b57cec5SDimitry Andric 2870b57cec5SDimitry Andric /// A view that collects and prints a few performance numbers. 288e8d8bef9SDimitry Andric class BottleneckAnalysis : public InstructionView { 2890b57cec5SDimitry Andric PressureTracker Tracker; 2900b57cec5SDimitry Andric DependencyGraph DG; 2910b57cec5SDimitry Andric 2920b57cec5SDimitry Andric unsigned Iterations; 2930b57cec5SDimitry Andric unsigned TotalCycles; 2940b57cec5SDimitry Andric 2950b57cec5SDimitry Andric bool PressureIncreasedBecauseOfResources; 2960b57cec5SDimitry Andric bool PressureIncreasedBecauseOfRegisterDependencies; 2970b57cec5SDimitry Andric bool PressureIncreasedBecauseOfMemoryDependencies; 2980b57cec5SDimitry Andric // True if throughput was affected by dispatch stalls. 2990b57cec5SDimitry Andric bool SeenStallCycles; 3000b57cec5SDimitry Andric 3010b57cec5SDimitry Andric struct BackPressureInfo { 3020b57cec5SDimitry Andric // Cycles where backpressure increased. 3030b57cec5SDimitry Andric unsigned PressureIncreaseCycles; 3040b57cec5SDimitry Andric // Cycles where backpressure increased because of pipeline pressure. 3050b57cec5SDimitry Andric unsigned ResourcePressureCycles; 3060b57cec5SDimitry Andric // Cycles where backpressure increased because of data dependencies. 3070b57cec5SDimitry Andric unsigned DataDependencyCycles; 3080b57cec5SDimitry Andric // Cycles where backpressure increased because of register dependencies. 3090b57cec5SDimitry Andric unsigned RegisterDependencyCycles; 3100b57cec5SDimitry Andric // Cycles where backpressure increased because of memory dependencies. 3110b57cec5SDimitry Andric unsigned MemoryDependencyCycles; 3120b57cec5SDimitry Andric }; 3130b57cec5SDimitry Andric BackPressureInfo BPI; 3140b57cec5SDimitry Andric 3150b57cec5SDimitry Andric // Used to populate the dependency graph DG. 3160b57cec5SDimitry Andric void addRegisterDep(unsigned From, unsigned To, unsigned RegID, unsigned Cy); 3170b57cec5SDimitry Andric void addMemoryDep(unsigned From, unsigned To, unsigned Cy); 3180b57cec5SDimitry Andric void addResourceDep(unsigned From, unsigned To, uint64_t Mask, unsigned Cy); 3190b57cec5SDimitry Andric 320e8d8bef9SDimitry Andric void printInstruction(formatted_raw_ostream &FOS, const MCInst &MCI, 321e8d8bef9SDimitry Andric bool UseDifferentColor = false) const; 322e8d8bef9SDimitry Andric 3230b57cec5SDimitry Andric // Prints a bottleneck message to OS. 3240b57cec5SDimitry Andric void printBottleneckHints(raw_ostream &OS) const; 3250b57cec5SDimitry Andric void printCriticalSequence(raw_ostream &OS) const; 3260b57cec5SDimitry Andric 3270b57cec5SDimitry Andric public: 3280b57cec5SDimitry Andric BottleneckAnalysis(const MCSubtargetInfo &STI, MCInstPrinter &MCIP, 3290b57cec5SDimitry Andric ArrayRef<MCInst> Sequence, unsigned Iterations); 3300b57cec5SDimitry Andric 3310b57cec5SDimitry Andric void onCycleEnd() override; onEvent(const HWStallEvent & Event)3320b57cec5SDimitry Andric void onEvent(const HWStallEvent &Event) override { SeenStallCycles = true; } 3330b57cec5SDimitry Andric void onEvent(const HWPressureEvent &Event) override; 3340b57cec5SDimitry Andric void onEvent(const HWInstructionEvent &Event) override; 3350b57cec5SDimitry Andric 3360b57cec5SDimitry Andric void printView(raw_ostream &OS) const override; getNameAsString()337e8d8bef9SDimitry Andric StringRef getNameAsString() const override { return "BottleneckAnalysis"; } isSerializable()338fe6060f1SDimitry Andric bool isSerializable() const override { return false; } 3390b57cec5SDimitry Andric 3400b57cec5SDimitry Andric #ifndef NDEBUG dump(raw_ostream & OS,MCInstPrinter & MCIP)3410b57cec5SDimitry Andric void dump(raw_ostream &OS, MCInstPrinter &MCIP) const { DG.dump(OS, MCIP); } 3420b57cec5SDimitry Andric #endif 3430b57cec5SDimitry Andric }; 3440b57cec5SDimitry Andric 3450b57cec5SDimitry Andric } // namespace mca 3460b57cec5SDimitry Andric } // namespace llvm 3470b57cec5SDimitry Andric 3480b57cec5SDimitry Andric #endif 349